B4A Library MSDynamicGridView Library

Discussion in 'Additional libraries, classes and official updates' started by thedesolatesoul, Jan 13, 2015.

  1. thedesolatesoul

    thedesolatesoul Expert Licensed User

    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.
    Code:
    DynamicAdapter.Initialize("DA",NumCols, 100%x/NumCols, 100dip)
    You can add items to the Adapter at any time:
    Code:
    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:
    Code:
    '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:
    [​IMG]

    [​IMG]

    [​IMG]

    Samples:
    Drag drop demo: http://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: May 3, 2015
  2. thedesolatesoul

    thedesolatesoul Expert Licensed 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: May 24, 2015
  3. monki

    monki Active Member Licensed User

    hello thedesolatesoul,
    good work:)

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

    thedesolatesoul Expert Licensed 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.
     
  5. barx

    barx Well-Known Member Licensed User

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

    thedesolatesoul Expert Licensed User

    It depends on which Strings you choose. There is an option to use strings off paypal, and there is the option to use strings off a zip file.
     
  7. BarryW

    BarryW Active Member Licensed User

    Is $1 is enough for you yo share me ur library? Or how much is the minimum?

    Cuz I want this library... Tnx...
     
  8. incendio

    incendio Well-Known Member Licensed User

    Considering his work, 1$ might be to small.
     
  9. BarryW

    BarryW Active Member Licensed User

  10. keirS

    keirS Well-Known Member Licensed User

    Looks good. I already use ULV whats the advantages of this over ULV?
     
  11. thedesolatesoul

    thedesolatesoul Expert Licensed User

    The minimum is $0 ;)

    It may be. But $1 means different amounts to different people, so I cant really say.

    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.
     
    Multiverse app and Peter Simpson like this.
  12. BarryW

    BarryW Active Member Licensed 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)
     
  13. thedesolatesoul

    thedesolatesoul Expert Licensed User

    To clear the items in the gridview you need to clear the items in the adapter.

    Code:
    DynamicAdapter.Clear
    DynamicAdapter.NotifyDataSetChanged
     
    Dave O likes this.
  14. BarryW

    BarryW Active Member Licensed User

    This library became slow when loading many images... any suggestion...?
     
  15. thedesolatesoul

    thedesolatesoul Expert Licensed User

    How are you loading the images?
     
  16. BarryW

    BarryW Active Member Licensed User

    I load it from a sqlite blob
     
  17. thedesolatesoul

    thedesolatesoul Expert Licensed User

    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?
     
  18. Dave O

    Dave O Active Member Licensed 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!
     

    Attached Files:

  19. Dave O

    Dave O Active Member Licensed 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:

    Code:
    Sub gridview_ItemClick(Position As Int)
       gridview.Selection = Position
    End Sub
    What does this do?

    Thanks!
     
  20. thedesolatesoul

    thedesolatesoul Expert Licensed User

    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.

    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.

    To be honest I cant remember, I was experimenting with item selection, and that code was wrong. Currenty I dont think it does anything.
     
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice