B4A Library MSDynamicGridView Library

This library implements one kind of GridViews:

Android Version Support
This GridView doesnt work 100% on Andriod 2.3 and lower. The animations are not supported and also the events are not raised (due to a bug).

1. DynamicGridView
This gridview is very flexible. All items must be of the same height/width.
It can load layouts into a panel, so you can have different layouts in each grid cell. It is very flexible and powerful. More features include the ability to drag/drop.

Credits:
This is very important. Most of these libraries are based on the work and research of warwound. Also, I got some ideas from Informatix. But warwound's custom listview library and explanations are the reason there libraries are here, if you are not going to donate to me, I appreciate donating to him.

Usage:
The gridview is not as simple to use like the B4A Listview.
It is more complex and rely on the concept of Adapters. If you have used Informatix's ULV you will be more familiar with the format.

Databinding:
The Gridview itself does not hold any data (String/Int/Customtype anything).
As a user it is your job to bind the data to a cell in a gridview using an ItemID or a ItemTag.
An ItemID is a unique ID for each cell of the Grid. This is generated internally.
An ItemTag is also unique for each item but it allows you to pass more complex data. This can allow you to change the appearance or layout of items by passing some tags.

This is where we get to the concept of an Adapter.

Adapters:
The adapter is responsible to create a layout and fetch the data to display in the views of the listview. Since listviews/gridviews can scroll and hold large amounts of data, the Adapters can recycle items into and out of the view.

MSDynamicAdapter:
The adapter needs to know the number of columns and width and height of each cell on initialization.
B4X:
DynamicAdapter.Initialize("DA",NumCols, 100%x/NumCols, 100dip)
You can add items to the Adapter at any time:
B4X:
    For i = 0 To 50
        DynamicAdapter.Add("Item " & i)
    Next
The ItemTag does need to be unique but we also internally always generate a unique ItemID. You can use ItemTag to make certain cells look similar, or hold certain kinds of data.

The Adapter will raise two events:
- GetLayout
- GetContent

In GetLayout you must create a new panel, load the layout by code or designer, and return the panel.
You should not really bind any content to your views here.

In GetContent you will get the ContentPanel in the parameters. Use ContentPanel.GetView to find your labels and imageviews etc, and then assign the values here like label.text and imageview.background etc.

It is important to understand adapters before you really move on.

Adapter Events Signature:
GetLayout
(Position as Int, ItemID as Long , ItemTag as String) as Panel
Create a panel in this event and return it, that will be used as the layout for the cell.
You can use Postion/ItemID/ItemTag to differenciate the layout.

GetContent (Position as Int , ItemID as Long , ItemTag as String , ContentPanel as Panel) as Panel
In this event you can used ItemID/ItemTag/Position to pull your data (from a list/map/db) and put that data onto the views in ContentPanel. You can find the views using GetView, or maybe use Tags.

GridView:

The Gridview is very simple. Just initialize it with an eventname, and add it to your activity.
You can set the adapter with:
B4X:
'Set the Gridview's adapter
    DynamicGrid.Adapter = DynamicAdapter.GetAdapter
This allows you to quickly change all the data the grid is holding!

Set the NumColums(DynamicGrid) the same as that set for the adapter.

Screenshots:
1127vxl.jpg


2r78rx2.jpg


15heghv.jpg


Samples:
Drag drop demo: https://www.b4x.com/android/forum/threads/drag-and-drop-gridview.46242/#content
Public demo: https://play.google.com/store/apps/details?id=com.maximussoft.picpuzzle

<to be continued>
 
Last edited:

thedesolatesoul

Expert
Licensed User
Longtime User
MSFlexGridView
Author:
thedesolatesoul
Version: 0.51
  • MSDynamicAdapter
    Events:
    • GetContent (Position as Int As , ItemID as Long As , ItemTag as String As , ContentPanel as Panel) as Pane As )
    • GetLayout (Position as Int As , ItemID as Long As , ItemTag as String) as Pane As )
    Methods:
    • Add (ItemTag As String)
    • Clear
    • GetAdapter As B4ADynamicGridAdapter
    • GetCount
    • GetItemIDFromPosition (position As Int) As Long
    • GetItemTagFromPosition (position As Int) As String
    • GetItems As List
    • Initialize (pEventName As String, columnCount As Int, ItemWidth As Int, ItemHeight As Int)
    • IsInitialized As Boolean
    • NotifyDataSetChanged
    • Remove (ItemTag As String)
    • getItem (position As Int) As Object
    • reorderItems (originalPosition As Int, newPosition As Int)
    Properties:
    • ColumnCount As Int
  • MSDynamicGridView
    Events:
    • ItemClick (Position as Int As )
    • ItemDragPositionsChanged (OldPosition as Int As , NewPosition as In As )
    • ItemDragStart (Position as Int As )
    • ItemDrop
    • ItemLongClick (Position as Int As )
    Methods:
    • BringToFront
    • GetFirstVisiblePosition As Int
    • GetLastVisiblePosition As Int
    • Initialize (arg1 As String)
    • Invalidate
    • Invalidate2 (arg0 As Rect)
    • Invalidate3 (arg0 As Int, arg1 As Int, arg2 As Int, arg3 As Int)
    • IsInitialized As Boolean
    • RemoveView
    • RequestFocus As Boolean
    • ScrollBy (x As Int, y As Int)
    • ScrollTo (position As Int)
    • SendToBack
    • SetBackgroundImage (arg0 As Bitmap)
    • SetColorAnimated (arg0 As Int, arg1 As Int, arg2 As Int)
    • SetLayout (arg0 As Int, arg1 As Int, arg2 As Int, arg3 As Int)
    • SetLayoutAnimated (arg0 As Int, arg1 As Int, arg2 As Int, arg3 As Int, arg4 As Int)
    • SetVisibleAnimated (arg0 As Int, arg1 As Boolean)
    • StartEditMode
      Start edit mode without starting drag;
    • StartEditModeFromPosition (position As Int)
      Start edit mode with position. Useful for start edit mode in
      {@link android.widget.AdapterView.OnItemClickListener}
      or {@link android.widget.AdapterView.OnItemLongClickListener}
    • StopEditMode
    • isEditMode As Boolean
    • isEditModeEnabled As Boolean
    • isUndoSupportEnabled As Boolean
    • isWobbleInEditMode As Boolean
    Properties:
    • Adapter As Adapter [write only]
    • Background As Drawable
    • Color As Int [write only]
    • ColumnWidth As Int [read only]
    • EditModeEnabled As Boolean [write only]
    • Enabled As Boolean
    • Height As Int
    • Left As Int
    • NumColumns As Int
    • OnEditModeChangeListener As OnEditModeChangeListener [write only]
    • ScrollY As Int
    • Tag As Object
    • Top As Int
    • Visible As Boolean
    • Width As Int
    • WobbleInEditMode As Boolean [write only]



Setup and Requirements:
1. You need android-support-v4.jar in your AdditionalLibs folder. Copy this from your SDK extras directory. For e.g. C:\Android\adt-bundle-windows-x86_64\sdk\extras\android\support\v4
Make sure to update your SDK to the latest.

2. Unzip the res.zip file to a known location. In your project you need to add:
H:\MyProjects\Github_masters\DynamicGrid-master\DynamicGrid-master\dynamicgrid\res
With your path pointing to the res file path you just unzipped.

3. Copy the MSDynamicGridView (xml and jar) file to your AdditionalLibs folder.

Licence & Download
Donations are voluntary and upto users discretion. This library is free to use.
Download MSDynamicGridView
Donate for MSDynamicGridView
 
Last edited:

monki

Active Member
Licensed User
Longtime User
hello thedesolatesoul,
good work:)

You can also load the flex grid on a panel ?
When will you be the libary published ?
thanks
monki
 

thedesolatesoul

Expert
Licensed User
Longtime User
hello thedesolatesoul,
good work:)

You can also load the flex grid on a panel ?
When will you be the libary published ?
thanks
monki
Hi monki,
Yes you can load it onto a panel as well.
Currently one of my testers reported some crashes so i am investigating that.
Also, the ClickEvent is not working on the SGV so i am also investigating that.
Keep in mind this library may come with strings attached.
 

barx

Well-Known Member
Licensed User
Longtime User
Hi monki,
Yes you can load it onto a panel as well.
Currently one of my testers reported some crashes so i am investigating that.
Also, the ClickEvent is not working on the SGV so i am also investigating that.
Keep in mind this library may come with strings attached.

Will these strings be in an Array, Map, or List?
 

BarryW

Active Member
Licensed User
Longtime User
Is $1 is enough for you yo share me ur library? Or how much is the minimum?

Cuz I want this library... Tnx...
 

keirS

Well-Known Member
Licensed User
Longtime User
Looks good. I already use ULV whats the advantages of this over ULV?
 

thedesolatesoul

Expert
Licensed User
Longtime User
Is $1 is enough for you yo share me ur library? Or how much is the minimum?
Cuz I want this library... Tnx...
The minimum is $0 ;)

Considering his work, 1$ might be to small.
It may be. But $1 means different amounts to different people, so I cant really say.

Looks good. I already use ULV whats the advantages of this over ULV?
Its hard (read impossible) to compete with ULV. The ULV has a lot of extra features like ListAnimator, Cache, Async Loaders etc, that are technically not part of a listview but aid in its usage. It still has a lot of related features like sections and hierarchy.
The MSDynamicGridView contains none of that. It is a lot more simpler and based on the compat gridview library. The user is expected to deal with the content, and the gridview deals with the display.
The main use case of this over the ULV is essentially the Grid capability i.e. ULV has one item per row, but I think it can deal with cells but I havent dealt with cells. That is a bit rigid approach i.e. you cannot re-flow the items on a wider or narrow screen. While the gridview allows you to deal with individual items.
Also it allows you to drag and drop items/cells.
I tried to include a staggeredgridview as well, but i just couldnt get the click event working, so I gave up on it.
 

BarryW

Active Member
Licensed User
Longtime User
How to clear the content of this gridview. Because when im trying to load again all the content it giving me an error.

java.lang.IndexOutOfBoundsException: Invalid index 30, size is 30
at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
at java.util.ArrayList.get(ArrayList.java:308)
at anywheresoftware.b4a.objects.collections.List.Get(List.java:117)
at com.escalera.jco2.main._da_getcontent(main.java:856)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:175)
at com.maximussoft.gridviews.B4ADynamicGridAdapter.getView(B4ADynamicGridAdapter.java:66)
at android.widget.AbsListView.obtainView(AbsListView.java:2308)
at android.widget.GridView.onMeasure(GridView.java:1044)
at android.view.View.measure(View.java:16772)
at android.view.ViewGroup.measureChild(ViewGroup.java:5110)
at android.view.ViewGroup.measureChildren(ViewGroup.java:5087)
at anywheresoftware.b4a.BALayout.onMeasure(BALayout.java:64)
at android.view.View.measure(View.java:16772)
at android.view.ViewGroup.measureChild(ViewGroup.java:5110)
at android.view.ViewGroup.measureChildren(ViewGroup.java:5087)
at anywheresoftware.b4a.BALayout.onMeasure(BALayout.java:64)
at android.view.View.measure(View.java:16772)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5139)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
at android.view.View.measure(View.java:16772)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5139)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1404)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:695)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:588)
at android.view.View.measure(View.java:16772)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5139)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2294)
at android.view.View.measure(View.java:16772)
at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:1936)
at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1133)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1315)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1020)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5762)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:771)
at android.view.Choreographer.doCallbacks(Choreographer.java:574)
at android.view.Choreographer.doFrame(Choreographer.java:544)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:757)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:149)
at android.app.ActivityThread.main(ActivityThread.java:5257)


at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:609)
at dalvik.system.NativeStart.main(Native Method)
 

thedesolatesoul

Expert
Licensed User
Longtime User
How to clear the content of this gridview. Because when im trying to load again all the content it giving me an error.
To clear the items in the gridview you need to clear the items in the adapter.

B4X:
DynamicAdapter.Clear
DynamicAdapter.NotifyDataSetChanged
 

BarryW

Active Member
Licensed User
Longtime User
This library became slow when loading many images... any suggestion...?
 

thedesolatesoul

Expert
Licensed User
Longtime User
I load it from a sqlite blob
Its hard to tell without seeing some code.
The way I do it though, is I load for e.g. 50 images in advance (which is a bit slow on first fetch), and hold them in memory. When the user clicks 'Next', it loads the next 50 images.
How big are the images you are fetching from the DB? Are they thumbnails?
 

Dave O

Well-Known Member
Licensed User
Longtime User
Just added the draggable gridview to my app and have it working. It was pretty simple to get up and running, by just taking your sample code and tweaking it for my layout and data source. Pic attached.

I did notice something surprising (to me) - In the GetContent event, I'm loading the thumbnail from storage into the panel (using Bitmap.InitializeSample), thinking that this would get called whenever that panel comes into view. (That is, I assumed it might get recycled if the grid had lots of items and it scrolled out of view and was reclaimed for another item.)

However, when I drag items, there is a perceptible pause when they pass over other items. Adding a few log statements revealed that GetContent is being called during drag (it looks like twice for the target item, once for the source item). This happens even if there is no scrolling (only a few items) in the gridview.

For now, I can change my code to load the images once from storage and keep the thumbnails in memory, then referencing just the thumbnails during GetContent.

But is it really necessary to call GetContent constantly like that? (Perhaps I'm misunderstanding how it works under the hood.)

Thanks!
 

Attachments

  • 2015-04-05 07.21.25.png
    2015-04-05 07.21.25.png
    65.9 KB · Views: 821

Dave O

Well-Known Member
Licensed User
Longtime User
The gridview is working well so far. Now that I've preloaded the thumbnails, the drag and drop is smooth.

I'm thinking of adding a shortcut where, after reordering items with drag-and-drop, the user can double-click an item to close the activity and return to that page in the prototype. However, there's no double-click event that I could find. Is this easy to add, or should I just track 2 clicks myself (e.g. with a timer)?

Also, I noticed this sub in your sample app:

B4X:
Sub gridview_ItemClick(Position As Int)
   gridview.Selection = Position
End Sub

What does this do?

Thanks!
 

thedesolatesoul

Expert
Licensed User
Longtime User
I did notice something surprising (to me) - In the GetContent event, I'm loading the thumbnail from storage into the panel (using Bitmap.InitializeSample), thinking that this would get called whenever that panel comes into view. (That is, I assumed it might get recycled if the grid had lots of items and it scrolled out of view and was reclaimed for another item.)

However, when I drag items, there is a perceptible pause when they pass over other items. Adding a few log statements revealed that GetContent is being called during drag (it looks like twice for the target item, once for the source item). This happens even if there is no scrolling (only a few items) in the gridview.
Interesting I havent noticed this at all. What I see is just GetContent for Position0 is called twice, but all the others are called only once.
What I did notice indeed is that if I do load the thumbnails or generate the thumbnails, indeed scrolling and dragging becomes slower. Thats why if you notice in my sample I do cache the thumbnails (but not the full picture), otherwise the performance is just not good.
If you post the code in GetLayout and GetContent I can check and see if I can improve the performance.

I'm thinking of adding a shortcut where, after reordering items with drag-and-drop, the user can double-click an item to close the activity and return to that page in the prototype. However, there's no double-click event that I could find. Is this easy to add, or should I just track 2 clicks myself (e.g. with a timer)?
Double-click isnt really a standard Android gesture (there is long click instead). You can get double tap I believe with the Gesture Detector library.

Also, I noticed this sub in your sample app:

B4X:
Sub gridview_ItemClick(Position As Int)
   gridview.Selection = Position
End Sub
What does this do?
To be honest I cant remember, I was experimenting with item selection, and that code was wrong. Currenty I dont think it does anything.
 
Top