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:

Dave O

Well-Known Member
Licensed User
If you post the code in GetLayout and GetContent I can check and see if I can improve the performance.

Actually, it's quite smooth now that I'm caching the thumbnails in a map at the beginning:

B4X:
Sub generateSketchThumbnails
   thumbnailMap.Initialize
   Dim sketchPath As String = common.buildProtoFolderPath(common.currentProto.id, common.CURRENT_DATA_VERSION)
   For Each pageInstance As sketchPage In common.pageList
     Dim sketchName As String = common.buildSketchFileName(pageInstance.pageID)
     Try
       Dim tempBitmap As Bitmap
       tempBitmap.InitializeSample(sketchPath, sketchName, itemWidth, itemHeight)
       thumbnailMap.put(common.castToString(pageInstance.pageID), tempBitmap)
     Catch
       Msgbox("This page's sketch could not be thumbnailed: " & pageInstance.pageID, "generateSketchThumbnails")
     End Try
   Next
End Sub

...then fetching the thumbnail as needed:

B4X:
Sub adapter_GetContent(Position As Int, ItemID As Long, itemTag As String, contentPanel As Panel) As Panel
   contentPanel.SetBackgroundImage(thumbnailMap.Get(common.castToString(itemTag)))   
   Dim tempLabel As Label = contentPanel.GetView(0)
   tempLabel.Text = common.buildFullPageName(common.getPageFromID(itemTag))
   Return contentPanel
End Sub
 

Dave O

Well-Known Member
Licensed User
For double-click, I didn't want to add another listener for Gesture Detector (wasn't sure how nicely it would play with the gridview's listener), so I just watched the click event for successive taps within a short time period. A bit hacky, but it's simple and it works:

B4X:
Sub gridview_ItemClick(Position As Int)
   Dim tempId As Int = adapter.GetItemTagFromPosition(Position)
   If tempId = idClickedJustBefore Then      'interpret as a double-click
     doubleClickTimer.Enabled = False
     returnPageId = tempId                   'return to the double-clicked page
     okButton_Click
   Else
     idClickedJustBefore = tempId
     doubleClickTimer.Enabled = True
   End If
End Sub

Sub timer_Tick
   doubleClickTimer.Enabled = False
   idClickedJustBefore = 0
End Sub

And it makes for a nice shortcut. Otherwise, with no selection visible, it's not clear which page is being returned to.
 
Last edited:

DonManfred

Expert
Licensed User
i dont know whethere there is a touchevent or not.
This java-code seems to do the wanted (i think it should work from reading the code)
Found here.
B4X:
public boolean onTouch(View v, MotionEvent event) {
            // TODO Auto-generated method stub
            if(firstTap){
                thisTime = SystemClock.uptimeMillis();
                firstTap = false;
            }else{
                prevTime = thisTime;
                thisTime = SystemClock.uptimeMillis();

                //Check that thisTime is greater than prevTime
                //just incase system clock reset to zero
                if(thisTime > prevTime){

                    //Check if times are within our max delay
                    if((thisTime - prevTime) <= DOUBLE_CLICK_MAX_DELAY){

                        //We have detected a double tap!
                        Toast.makeText(DoubleTapActivity.this, "DOUBLE TAP DETECTED!!!", Toast.LENGTH_LONG).show();
                        //PUT YOUR LOGIC HERE!!!!

                    }else{
                        //Otherwise Reset firstTap
                        firstTap = true;
                    }
                }else{
                    firstTap = true;
                }
            }
            return false;
        }
 
Last edited:

asales

Well-Known Member
Licensed User
I tried to make an example (based in MultipleLayouts of MSDynamicGridView) to show the images of DirAssets, but don't work.

I get the error: "java.lang.ClassCastException: android.widget.ImageView cannot be cast to android.widget.TextView"

I don't know how to modify the DA_GetLayout to fix it.

Please, see the example in attached.

I glad for any help.
 

Attachments

  • grid.zip
    61.4 KB · Views: 121

asales

Well-Known Member
Licensed User
I tried to make an example (based in MultipleLayouts of MSDynamicGridView) to show the images of DirAssets, but don't work.

I get the error: "java.lang.ClassCastException: android.widget.ImageView cannot be cast to android.widget.TextView"

I don't know how to modify the DA_GetLayout to fix it.

Please, see the example in attached.

I glad for any help.

I found the error!!!
I don't modify the DA_GetContent, that used a label from original example.

Solved with this code (until now):
B4X:
Sub DA_GetContent(Position As Int, ItemID As Long, ItemTag As String, ContentPanel As Panel) As Panel
    Dim iv1 As ImageView = ContentPanel.GetView(0)
    iv1.Tag = GridItems.Get(ItemID)
    Return ContentPanel
End Sub
 

asales

Well-Known Member
Licensed User
Now is a real issue:
I read the images of DirAssets but the order is missing when I scrolled the grid.

When start is ok (shows the images 0 to 7), but don't shows the images 8 and 9.
When I return to the top of grid the number is changed: 0 - 1 -> 1 - 0

I don't understand what is happening (new example and images in attached)?

img1.png img2.png img3.png
 

Attachments

  • grid_2.zip
    62.5 KB · Views: 133

asales

Well-Known Member
Licensed User
Now is a real issue:
I read the images of DirAssets but the order is missing when I scrolled the grid.

When start is ok (shows the images 0 to 7), but don't shows the images 8 and 9.
When I return to the top of grid the number is changed: 0 - 1 -> 1 - 0

I don't understand what is happening (new example and images in attached)?

View attachment 34518 View attachment 34519 View attachment 34520

Solved again with this code:
B4X:
Sub DA_GetContent(Position As Int, ItemID As Long, ItemTag As String, ContentPanel As Panel) As Panel
    Dim Bitmap1 As Bitmap
    Bitmap1.Initialize(File.DirAssets ,GridItems.Get(ItemID))    'relat_02

    Dim iv1 As ImageView = ContentPanel.GetView(0)
    iv1.Bitmap = Bitmap1

    Return ContentPanel
End Sub
 

shashkiranr

Active Member
Licensed User
Hi @thedesolatesoul and All,

I wanted to use this library inside an item of Ultimate List view but i keep on getting Null Pointer exception. I want a grid view in the items. Is it possible for this to happen. I am trying to find alternatives.

Thank you for your kind attention.

Regards,
SK
 

thedesolatesoul

Expert
Licensed User
Hi @thedesolatesoul and All,

I wanted to use this library inside an item of Ultimate List view but i keep on getting Null Pointer exception. I want a grid view in the items. Is it possible for this to happen. I am trying to find alternatives.

Thank you for your kind attention.

Regards,
SK
It should be possible to put it in there, but it wont scroll anymore.
I have to say it will be very tricky as you would have to Dim the gridview inside the LayoutCreator. Its possible that the adapter within adapter would cause a problem in re-drawing.
If you have a sample that demonstrates the issue we can try to see whats going on (if you think that is the correct solution for you).
 

shashkiranr

Active Member
Licensed User
Hi @thedesolatesoul ,

I was able to integrate the grid view in the ULV item but is there a way I can get the height of the complete grid view? The GridView.Height is returning -1 even after the grid view is added.

Regards,
SK
 

thedesolatesoul

Expert
Licensed User
Hi @thedesolatesoul ,

I was able to integrate the grid view in the ULV item but is there a way I can get the height of the complete grid view? The GridView.Height is returning -1 even after the grid view is added.

Regards,
SK
Can you tell me how you add the grid to the ulv? ContentPanel.AddView?
[sorry im quite slow on responses these days]
 

shashkiranr

Active Member
Licensed User
Hi @thedesolatesoul ,

I first added a panel in the layout creater of ULV to hold the entire grid view. Then in the content filler i added the gridview items. The images are loading properly but since the ULV picks up the scrolling function, the gridview images that are not displayed cannot be seen. Hence I wanted to change the height of of each item of ULV so that all complete gridview is seen but the gridview height is -1(fill parent).

Hope this helps.

Regards,
SK
 
Top