B4A Library [Class] CheckList

Hi,

I created a class to manage a list with checkboxes (but not only, you can use it for any kind of list with rows). The layout is highly customizable and you can even extend a clicked item with extra content. You can rearrange the items programmatically or manually (drag & drop).

Tutorials: How they do #1, How they do #3

img1.jpg img2.jpg img3.jpg img4.jpg img5.jpg

v1.1: I added the ExtendItem function and an option to check the box when items are added

v1.2: I fixed the width problem (in a container like TabHost, the width property returns -1, so we have to use a different method to get the SV width) and, in the demo, a click on the extended item collapses now its content.

v1.3: I added a new function to add items without checkbox (AddItemNoChkbx) so you can use this class as a ListView replacement;
I changed the way it colors the selected item (now it complies to the default Android theme);
I added an option to color differently the extended item.

v1.4: I optimized the code a little bit and I added three functions:
AddCustomItem (adds your own layout to the list);
AdjustBitmap (resizes the bitmap to fit the given dimensions);
GetFirstText (returns the first label text found for the given ID).

v1.5: I simplified and improved the management of extended items (I also fixed a bug). Unfortunately, that could break existing code.
Inspired by the class CustomListView, I added a parameter to Initialize: DividerHeight (if you want to put a colored divider between items) and several functions:
- NumberOfItems
- getHeight
- JumpToPosition
- JumpToItem
- CollapseItem
- HasExtraContent
- ExtendedItemID

v1.6:
Now, you can define the color of checked items and the background color (transparent by default).
I added two (very fast) functions:
- JumpToView (scrolls the list to the given view)
- FindPanelContaining (returns the panel containing the given view)
I added another example.

v2.0:
I added more than 10 new functions (MoveItem, RemoveItemAt, SwapItems, SortItems, ReplaceItem, ApplyColors, CreateTextList, etc.). See post #21 for complete list;
I changed the ID type (formerly Int) to Object (that shouldn't break the existing code);
I added the Drag & Drop feature;
I optimized JumpToPosition (a lot quicker now);
I fixed a bug with colors.

v2.1:
I added functions to filter the list;
I added CreateIntegerList to ease the sorting and filtering of integer values;
Now you can change the item height in ReplaceItem.

v2.2:
I fixed a bug (BackgroundColor was not applied to new items)
I added new functions:
- FindPanelWithID(ID As Object) As Object
- SetOnPaintListener(SubName As String)
- Repaint(pnlItem As Panel)
I renamed ApplyColors to RepaintAllItems

v2.21:
I changed an incorrect declaration in the demo #1 and #2.
The class is now compatible with the obfuscation option.

v2.22:
The class no longer displays warnings with B4A v2.7x.
All examples are now compatible with the obfuscation option.

Complete list of functions here

Fred

PS: you need the Reflection Lib
 

Attachments

  • CheckList v2.22.zip
    60.2 KB · Views: 2,047
Last edited:

Informatix

Expert
Licensed User
Longtime User
New version 2.0:
I added more than 10 new functions;
I changed the ID type (formerly Int) to Object (that shouldn't break the existing code);
I added the Drag & Drop feature;
I optimized JumpToPosition (a lot quicker now);
I fixed a bug with colors.

COMPLETE LIST OF FUNCTIONS:

Initialize(Module As Object, svList As ScrollView, subCheck As String, subClick As String, subLongClick As String, DividerHeight As Int)
' Initializes the ScrollView.

AddItem(ID As Object, Checked As Boolean, Text1 As String, Text2 As String, Image As Bitmap)
' Adds a item (the created panel contains a checkbox, an optional bitmap and one or two labels)

AddItemNoChkbx(ID As Object, Text1 As String, Text2 As String, Image As Bitmap)
' Adds a item without checkbox (the created panel contains an optional bitmap and one or two labels)

AddCustomItem(ID As Object, pnl As Panel, pnlHeight As Int)
' Adds a custom item (a panel holding your custom layout)

AddHeader(Text As String)
' Adds a header

ResizePanel()
' Resizes the ScrollView panel height (must be called when all items are added)

MoveItem(StartPosition As Int, EndPosition As Int)
' Moves an item from StartPosition to EndPosition

SwapItems(PosItem1 As Int, PosItem2 As Int)
' Swaps the position of the given items

ReplaceItem(Position As Int, NewPanel As Panel, NewHeight As Int)
' Replaces an item panel by another

RemoveItemAt(Position As Int)
' Removes the item at the given position

RemoveItemID(ID As Object)
' Removes the item with the given ID

CreateTagList(ViewIndexInPanel As Int, FirstPosition As Int, LastPosition As Int) As List
' Creates a tag list with items between FirstPosition and LastPosition

CreateTextList(ViewIndexInPanel As Int, FirstPosition As Int, LastPosition As Int) As List
' Creates a text list with items between FirstPosition and LastPosition

CreateCheckedStateList(FirstPosition As Int, LastPosition As Int) As List
' Creates a checked state list (true/false) with items between FirstPosition and LastPosition

SortItems(ValuesToSort As List, FirstPosition As Int, LastPosition As Int, AscendingOrder As Boolean)
' Sorts the items between FirstPosition and LastPosition

getHeight()
' Gets the ScrollView height (works inside a TabHost)

getWidth()
' Gets the ScrollView width (works inside a TabHost)

NumberOfItems()
' Returns the number of items

FindPanelContaining(MyView As View) As Panel
' Returns the panel containing the given view.

AdjustBitmap(bmp As Bitmap, Width As Int, Height As Int) As Bitmap
' Resizes the bitmap to fit the given dimensions

GetFirstText(ID As Object) As String
' Returns the first label text found for the given ID

JumpToPosition(Position As Int) As Panel
' Scrolls the list to the given position

JumpToItem(ID As Object) As Panel
' Scrolls the list to the item with the given ID

JumpToView(MyView As View) As Panel
' Scrolls the list to the given view

CheckedList() As List
' Creates a list with ID of checked items

CheckedPanels() As List
' Creates a list with panels of checked items

CheckAllBoxes(Checked As Boolean)
' Checks/unchecks all checkboxes

RepaintAllItems()
' Applies the new colors (BackgroundColor, CheckedColor, DividerColor, ExtensionColor) to all items

ExtendItem(ItemID As Object, AddedContent As View, ContentHeight As Int)
' Adds an extra content (panel, label, edittext, imageview...) under an item

CollapseItem()
' Removes the extra content

HasExtraContent As Boolean
' Checks if there is an item with extra content

ExtendedItemID As Object
' Returns the ID of the item with extra content

StartDragAndDrop(pnl As Panel, subAfterDrop As String)
' Starts a drag&drop operation

AbortDragAndDrop()
' Aborts the current drag&drop operation

EDIT: New in version 2.1:

CreateIntegerList(ViewIndexInPanel As Int, FirstPosition As Int, LastPosition As Int) As List
' Creates an integer list with items between FirstPosition and LastPosition

FilterTag(ViewIndexInPanel As Int, ComparisonFunction As String) As Int
FilterText(ViewIndexInPanel As Int, ComparisonFunction As String) As Int
' Filters the items and returns the number of matching items.

IsFiltered(Position As Int) As Boolean
' Returns True if the item at the given position is filtered (not visible)

CancelFilter()
' Cancels the filter and displays all items

EDIT: New in version 2.2:

FindPanelWithID(ID As Object) As Object
' Returns the panel with the given ID

SetOnPaintListener(SubName As String)
' Defines an event handler called every time the item background is repaint

Repaint(pnlItem As Panel)
' Applies the new colors (BackgroundColor, CheckedColor, DividerColor, ExtensionColor) to the given item
 
Last edited:

Informatix

Expert
Licensed User
Longtime User
As you can see in the list, there's no Insert function. Technically, an insert is a add+move, so choose you Add method and move the added item to the right position (its StartPosition is NumberOfItems -1).

In demo #2, I didn't convert the quantities to numbers, hence the sort result with quantities > 9 (they are considered as strings).
 

Mahares

Expert
Licensed User
Longtime User
I tried to have ONE button to toggle between Check/Uncheck all items, but could not. I had to have 2 separate buttons: Error: Cannot parse as Boolean
B4X:
Sub tglCheck_CheckedChange(Checked As Boolean)
   If lst.CheckAllBoxes(False) Then
      lst.CheckAllBoxes(True) 
   Else
      lst.CheckAllBoxes(False) 
   End If
End Sub
Thank you
 

Informatix

Expert
Licensed User
Longtime User
I tried to have ONE button to toggle between Check/Uncheck all items, but could not. I had to have 2 separate buttons: Error: Cannot parse as Boolean
B4X:
Sub tglCheck_CheckedChange(Checked As Boolean)
   If lst.CheckAllBoxes(False) Then
      lst.CheckAllBoxes(True) 
   Else
      lst.CheckAllBoxes(False) 
   End If
End Sub
Thank you

CheckAllBoxes doesn't return anything, so you cannot use it this way.
You should use CheckedList to know how many checkboxes are checked and act accordingly. There's not only one answer because there are 3 states (all checked, all unchecked, mixed). One possible solution:
B4X:
If lst.CheckedList.Size > 0 Then
      lst.CheckAllBoxes(False) 
   Else
      lst.CheckAllBoxes(True) 
   End If
 

Mahares

Expert
Licensed User
Longtime User
You previous suggestion works well Fred.
As a minor observation, lst.CheckAllBoxes(True) takes a little bit of time as it navigates through all items one at a time, especially with 100 or more records, but lst.CheckAllBoxes(False) is instant.
Merci infiniment.
 

Informatix

Expert
Licensed User
Longtime User
You previous suggestion works well Fred.
As a minor observation, lst.CheckAllBoxes(True) takes a little bit of time as it navigates through all items one at a time, especially with 100 or more records, but lst.CheckAllBoxes(False) is instant.
Merci infiniment.

This function should run as fast in the two situations, because I do exactly the same thing when the parameter is true and when the parameter is false. And even on a slow device, the function can examine at least one thousand items in less than one second. I suppose the slowness is due to a CheckedChange event which does something when the box is checked. You must block this event when you call CheckAllBoxes (and fire it at the end if needed). The simplest solution is to use a boolean like the one used in the class (BlockCheckEvent).
 

Mahares

Expert
Licensed User
Longtime User
I used a button click event: Even on a fast device with 4.03 OS, it takes several seconds to check 560 records and about 1 second to uncheck them.
B4X:
'UnCheck / check all boxes to start all over
Sub btnUnCheck_Click   
   If lst.CheckedList.Size > 0 Then lst.CheckAllBoxes(False) Else lst.CheckAllBoxes(True) 

End Sub
Thank you for your reply.

Edited 29 july 12: The reason it takes a while when checked is because of the expansion. If I comment one line, see below code, it is instant like the UNcheck:
B4X:
Sub ChkBx_CheckedChange(Checked As Boolean)
   Dim pnl As Panel
   pnl = lst.FindPanelContaining(Sender)
   If Checked Then
'      ExpandItem(pnl, pnl.Tag)
   Else
 
Last edited:

Informatix

Expert
Licensed User
Longtime User
New version

v2.2:
I fixed a bug (BackgroundColor was not applied to new items)

I added new functions:
- FindPanelWithID(ID As Object) As Object
'Returns the panel with the given ID
- SetOnPaintListener(SubName As String)
'Defines an event handler called every time the item background is repaint
- Repaint(pnlItem As Panel)
'Applies the new colors (BackgroundColor, CheckedColor, DividerColor, ExtensionColor) to the given item

I renamed ApplyColors to RepaintAllItems
'Applies the new colors (BackgroundColor, CheckedColor, DividerColor, ExtensionColor) to all items

I updated the demo #2

You can set now a listener for the OnPaint events. That allows you to highly customize the appareance of the list.
 

moster67

Expert
Licensed User
Longtime User
Fred,

Finally I found some time to study your code/demos and an opportunity to implement some of your work in an app. This class is so flexible and playing around with it, I see many possible scenarios where it will be useful.

Thank you Fred for this incredible class. :sign0188:
 

Informatix

Expert
Licensed User
Longtime User
Fred,

Finally I found some time to study your code/demos and an opportunity to implement some of your work in an app. This class is so flexible and playing around with it, I see many possible scenarios where it will be useful.

Thank you Fred for this incredible class. :sign0188:

I am writing a class even better. With it you are able to load an almost unlimited number of items, including bitmaps, without risking an Out of Memory error. It also loads items faster. It won't probably be free (nothing is decided yet about the licensing model).
The idea is to offer exactly the same functions as CheckList. Thus a user will have just to substitute the old class by the new one.
 

moster67

Expert
Licensed User
Longtime User
Wow!

I am really impressed with your creativeness and professional coding. Look forward to that class too.
 

moster67

Expert
Licensed User
Longtime User
Fred,

maybe it is already possible (there are so many possibilities in your class) but I was unable to figure it out. Is there a way to make the LabelHeight adjust automatically - some kind of auto-wrapping?

For instance using this:

B4X:
lst.AddItemNoChkbx(i, "Example - Line #" & i, "Second line" & CRLF & "third line added by me", Null)

will not show third line added by me since the height of the label is not enough.

Normally I can use MeasureMultilineTextHeight from the StringUtil-library to adjust the label-height. I tried it within your class but I couldn't get it to work.

Any ideas how to to get auto-wrapping working?

Thanks!
 

Informatix

Expert
Licensed User
Longtime User
Fred,

maybe it is already possible (there are so many possibilities in your class) but I was unable to figure it out. Is there a way to make the LabelHeight adjust automatically - some kind of auto-wrapping?

It's not done automatically, but it's easy to implement:
If you want to modify the AddItemNoChkbx function, you must replace PanelHeight by the new panel height and LabelHeight by the new label height wherever you find them.
If you don't want to modify the class, copy the AddItemNoChkbx function in your Activity. Customize it and feed the AddCustomItem function with the created panel.
 
Last edited:

cstangor

Member
Licensed User
Longtime User
Checklist usage

I like this class a lot but I'm having trouble using it.

I'd like to have different checklists, but I don't know how to manage switching from one to another.

There seems to be only one possible instance of the class. Is this correct?

Thanks
 

fdx12345

Active Member
Licensed User
Longtime User
Cannot download

My computer states the file is a multi-volume and wants other files to go with it.

Bill
 

Informatix

Expert
Licensed User
Longtime User
There seems to be only one possible instance of the class. Is this correct?

Not at all. You can see in the following screenshot (from the ScrollPanel class example) that you can have different checklists at the same time, on the same screen:

12850d1342654780-class-scrollpanel-img1.jpg
 
Top