CustomListView - A flexible list based on ScrollView

Status
Not open for further replies.

shashkiranr

Active Member
Licensed User
Longtime User
Here is the code Erel.

The GetIfChecked Sub is checking if the checkbox is checked or not by retrieving from DB.

The CreateListItem creates the each item in the list along with checkbox.

The chk_CheckedChange is called each time the value of the checkbox

As you can see in the code. I am programatically setting the value of the checkbox when first creating the view and the sub chk_CheckedChange is called since the checkbox value is changed.

Now since the Sender is null it is throwing a NULL Pointer Exception.

B4X:
Sub CreateListItem(Text As String, Width As Int, Height As Int,chkflglan As Int) As Panel
    Dim p As Panel
    p.Initialize("")
    p.Color = Colors.Black
  
    chk.Initialize("chk")
    Dim lbl As Label
    lbl.Initialize("")
    lbl.Gravity = Bit.OR(Gravity.CENTER_VERTICAL, Gravity.LEFT)
    lbl.Text = Text
    lbl.TextSize = 20
    lbl.TextColor = Colors.White
  
    getIfCheked(chkflglan)

'Setting the Exisiting value for CheckBox
    If (CheckBoxFlag == True) Then
            chk.Checked = True
    End If
  
    p.AddView(lbl, 5dip, 2dip, 150dip, Height - 4dip) 'view #0
    p.AddView(chk, 280dip, 2dip, 50dip, Height - 4dip) 'view #2
    Return p
End Sub

Sub getIfCheked(langval As Int)
    Dim m As Map
    m = DBUtils.ExecuteMap(SQL, "SELECT Flag FROM languageSettings WHERE Language = ?", _
        Array As String(lan.lanlist(langval)))
    Log (" ** For Checkbox Query Result ** "& m.GetValueAt(0))
    If ((m.Get("flag") = Null) OR (m.Get("flag") = "0")) Then
        CheckBoxFlag = False
    End If
    If ((m.Get("flag")) = "1") Then
        CheckBoxFlag = True
    End If
End Sub

Sub chk_CheckedChange(Checked As Boolean)

        Dim index As Int
        index = clv1.GetItemFromView(Sender)
        Log("*** Sender **"&Sender)
        Dim pnl As Panel
        pnl = clv1.GetPanel(index)
        Dim chk1 As CheckBox
        chk1.Initialize("chk1")
        chk1= pnl.GetView(1)
        Log("Item value: " & clv1.GetValue(index) &"Check value: " & chk1.Checked)

        updateInDB(clv1.GetValue(index),chk1.Checked)

End Sub

Kindly let me know the if i am making any mistake.

Regards,
SK
 

shashkiranr

Active Member
Licensed User
Longtime User
Erel,

There is no breakpoint before this sub while debugging !!
All i am doing is retrieving values and setting the checkbox .checked value for the first time when i am loading the list view

now since the value is changed it is calling chk_CheckedChange sub and getting the exception.

if i remove the retrieving and setting of checkbox i m not getting any exception.

Am i missing something ??

Regards,
SK
 

Mashiane

Expert
Licensed User
Longtime User
Toggle Button Code

I wanted to add a toggle button and determine its state in this module. Here is the code...

B4X:
' add a label and a toggle button to listview
Sub AddLabelToggleButton(Text As String, Width As Int, Height As Int, bState As Boolean) As Panel
    Dim p As Panel
    p.Initialize("")
    p.Color = Colors.Black
    Dim tb As ToggleButton
    tb.Initialize("toggleb")
    tb.TextOff = "Off"
    tb.TextOn = "On"
    tb.Checked = bState
    Dim lbl As Label
    lbl.Initialize("")
    lbl.Gravity = Bit.OR(Gravity.CENTER_VERTICAL, Gravity.LEFT)
    lbl.Text = Text
    lbl.TextSize = 16
    lbl.TextColor = Colors.White
    p.AddView(lbl, 5dip, 2dip, 150dip, Height - 4dip) 'view #0
    p.AddView(tb, 280dip, 2dip, 50dip, Height - 4dip) 'view #1
    Return p
End Sub

' return status of toggle button
Sub toggleb_CheckedChange(Checked As Boolean)
    ' the checked status is checked on each control creation.
   ' check if the list is still being loaded, if so dont execute
    if bLoading = True then Return
    Dim index As Int
    Dim sValue As String
    index = lstIntervals.GetItemFromView(Sender)
    Dim pnl As Panel
    pnl = lstIntervals.GetPanel(index)
    Dim tb As ToggleButton
    tb = pnl.GetView(1)
    sValue = lstIntervals.GetValue(index)
    Log(sValue & ": " & tb.Checked)
    Msgbox("Item value: " & sValue & CRLF & "Check value: " & tb.Checked, "")
End Sub

I must say this ListView module is THEE BOMB!!
 
Last edited:

GMan

Well-Known Member
Licensed User
Longtime User
Is it possible to "create" a 3 state button ?
 

Mashiane

Expert
Licensed User
Longtime User
@ shashkiranr

The reason for the Null Pointer exception is because the checked state of each checkbox being added during runtime. I had a similar issue with my code yesterday. You can do define a variable and assign it to True whilst your list is loading. On the CheckChanged stage of the checkbox, check if that variable is True and if True exit the code.

When adding items to the list the CheckChanged state also changes when each item is added, and the system checks that.

B4X:
You can place this variable definition on Globals
Dim bLoaded as Boolean = True

' put on the sub to load the list of items
bLoaded = True
For i = 0 to 10
CreateListItem...
Next
bLoaded = False

' now on _CheckChanged sub
if bLoaded = True Then Return
 

mc73

Well-Known Member
Licensed User
Longtime User
Don't know if this is already included, I just didn't have it in the copy I downloaded. Inside the class, I added
B4X:
Private Sub Panel_LongClick
   If SubExists(CallBack, EventName & "_LongItemClick") Then
     Dim v As View
     v = Sender
     CallSub3(CallBack, EventName & "_LongItemClick", v.Tag, items.Get(v.Tag))
   End If
End Sub

Just to get the long click event, since I needed it for something (obviously).
 

coslad

Well-Known Member
Licensed User
Longtime User
Hi, is there a way to know if the list is scrolled at the end? I don't want to load all the list at beginning.
Thanks
 

coslad

Well-Known Member
Licensed User
Longtime User
I found the solution :

i added this sub to the class

B4X:
Sub SV_ScrollChanged(Position As Int)
If sv.Height + Position >= sv.Panel.Height Then
    If SubExists(CallBack, EventName & "_bottom") Then
        Dim v As View
        v = Sender
        CallSub(CallBack, EventName & "_bottom")
    End If
 
End If
End Sub

and at the top of the class this code :

B4X:
#Event: bottom

and woks fine !!!!!!!
 
Last edited:

bsnqt

Active Member
Licensed User
Longtime User
Hi Erel,

I see a strange thing in my demo CustomListView (see attached). Actually it is your original sample but I just list all the views inside a panel from the listview item. With the following code we can see that the checkbox in the listview is actually a button. I don't understand what is wrong with my code?

Thank you.

B4X:
    Dim v As View
    For i = 0 To pnl.NumberOfViews - 1
        v = pnl.GetView(i)
        If v Is Button Then
            Dim btn As Button = v
            Log(i)
            If btn.Text <> "Click" Then
                btn.Visible = True
                btn.Color = Colors.Red
            End If
        End If
    Next
 

Attachments

  • TestCustomListView.zip
    9.7 KB · Views: 231
  • Screenshot.png
    Screenshot.png
    92.8 KB · Views: 434

ciprian

Active Member
Licensed User
Longtime User
I am using your exemple and BetterDialogs Library. I wish when i'm doing a lbl_longclick to show a CustomDialog inviting the user to change the lbl.text.
How can i do that? I'm searching for hours already.....i'm blocking.
Please show me the way.
B4X:
Sub Activity_Create(FirstTime As Boolean)   
    clv1.Initialize(Me, "clv1")
    Activity.AddView(clv1.AsView, 0%x, 10%y, 100%x, 90%y)
    For i = 1 To 16
        clv1.Add(CreateListItem("Relais " & i, clv1.AsView.Width, 50dip), 50dip, "Relais " & i)
    Next   
End Sub
Sub CreateListItem(Text As String, Width As Int, Height As Int) As Panel
    Dim p As Panel
    p.Initialize("")
    p.Color = Colors.Black   
    Dim b As Button            'all buttons click events will be handled with Sub Button_Click
    b.Initialize("button")   
    Dim tog As ToggleButton  'all toggle_buttons click events will be handled with Sub Toggle_Button Checked_Change
    tog.Initialize("tog")
    tog.Checked = False
    tog.TextOn = "ON"
    tog.TextOff = "OFF"
    Dim chk As CheckBox
    chk.Initialize("chk")   
    Dim lbl As Label
    lbl.Initialize("lbl")
    lbl.Gravity = Bit.OR(Gravity.CENTER_VERTICAL, Gravity.LEFT)
    lbl.Text = Text
    lbl.TextSize = 16
    lbl.TextColor = Colors.White
    b.Text = "Pulse"
    p.AddView(lbl, 5dip, 2dip, 150dip, Height - 4dip) 'view #0
    p.AddView(b, 155dip, 2dip, 110dip, Height - 4dip) 'view #1
    p.AddView(tog, 280dip, 2dip, 60dip, Height - 4dip) 'view #3
    Return p   
End Sub

Sub lbl_LongClick
    Dim index As Int
    index = clv1.GetItemFromView(Sender)
    Dim lbl As Label
    lbl.Initialize("lbl")
'    Msgbox(clv1.GetValue(index), "Rename ?")
    'Message box
    Dim DR As Int
    Log("DR=" & DR)
    Dim IP As BD_InputBoxParams
    IP.Initialize
    IP.Question = "<I>Rename Relais 1? </I>"
    IP.QuestionTextSize = 18
    IP.SpaceBetween = 4dip
    IP.InputTextSize = 24
    IP.InputType = IP.INPUT_TYPE_TEXT_WITH_CAPS
    IP.Gravity = Gravity.CENTER_VERTICAL + Gravity.CENTER_HORIZONTAL
    IP.ValidationCallback = "Input_Validation"
    IP.WithSuggestions = True
    DR = BD.InputBox("New Name", IP, "OK", "Cancel", "", LoadDrawable("ic_menu_edit"))
    Log("DR=" & DR)
    If DR = DialogResponse.POSITIVE Then
        Log(IP.Answer)
        Log(IP.CompactAnswer)
        lbl.Text=(IP.Answer) 'not working...
    Else 

    End If
   
    Dim btnOK As Button
    btnOK.Initialize("")
    btnOK.Background = CreateStateListDrawable
    btnOK.Text = "<Font Color='Yellow'>O</Font>K"
    btnOK.TextColor = Colors.White

    Dim btnCancel As Button
    btnCancel.Initialize("")
    btnCancel.Text = "<Font Color='Yellow'>C</Font>ancel"
    btnCancel.TextColor = Colors.White
    btnCancel.Background = CreateStateListDrawable
End Sub

What is wrong in my code?
 
Status
Not open for further replies.
Top