B4A Library [B4X] CLVBackwards - xCLV extenstion for lists that grow backwards

This class can be helpful in esoteric cases where the list grows up instead of down. Think of a chat app where you start with the most recent messages and when the user scrolls up, more older messages are added to the top.

The challenge here is to add items without making the list jump back and forth.
It is important to understand how it is implemented as it affects the usage.
When CLVBackwards is initialized, it adds a very large "spacer" item as the first CLV item.
Later when we add items with Backwards.AddItem, the item is inserted after the spacer, and the spacer becomes shorter. This way the list size never changes.

The class also handles the case where you want to remove the spacer. This is relevant if you don't want to insert more items at the top (and obviously the user shouldn't scroll into the large spacer).

Notes:
  1. Set the divider height to 0.
  2. Remove the scroll bars.
  3. See the example code and don't miss the call to IsReady.

The class is inside the cross platform example project.
 

Attachments

  • Project.zip
    16.7 KB · Views: 393

Erel

B4X founder
Staff member
Licensed User
Longtime User
i5ZHnaHUxJ.gif
 

GanjaKyp

Active Member
Licensed User
Why are elements rendered with such a delay?

B4X:
Sub CustomListView1_VisibleRangeChanged (FirstIndex As Int, LastIndex As Int)
    If Backwards.SpacerRemoved Then Return
   
    If FirstIndex <= 1 Then
        Dim StartingIndex As Int = CustomListView1.Size - 1
        For i = StartingIndex To Min(StartingIndex + 5, CustomListView1.Size)
            Backwards.AddItem(AddMessage(messages_list.Get(i)), Null)
        Next
   
        If LastIndex = 0 Then
            Sleep(0)
            Backwards.ScrollToItemNow(1)
        End If
    End If
   
    If CustomListView1.Size >= messages_list.Size Then
        Backwards.RemoveTheSpacer
    End If
End Sub

Sub AddMessage (m As Map) As Panel
    Dim p As B4XView = XUI.CreatePanel("")
    p.SetLayoutAnimated(0, 0, 0, CustomListView1.AsView.Width, 70dip)
    p.LoadLayout("chat_item")
    
    Dim p1 As Panel = p.GetView(0)

    ChatImageView.Bitmap = LoadBitmapResize(File.DirAssets, Rnd(1, 4) & ".jpg", ChatImageView.mBase.Width, ChatImageView.mBase.Height, True)
    
    Dim l1 As Label = p.GetView(2)
    l1.Text = m.Get("name")
    
    Dim l2 As Label = p.GetView(3)
    l2.Text = m.Get("text")
    l2.Height = Max(15dip, SU.MeasureMultilineTextHeight(l2, l2.Text))
    p.Height = l2.Top + l2.Height + 15dip
    p1.Height = p.Height - 5dip
    
    Dim l3 As Label = p.GetView(4)
    l3.Text = m.Get("datetime")

    Return p
End Sub

video_2022-04-19_20-27-54.gif
 
Last edited:

GanjaKyp

Active Member
Licensed User
I removed all unnecessary libraries, please see what could be wrong
 

Attachments

  • MarginMessanger.zip
    348.1 KB · Views: 86

GanjaKyp

Active Member
Licensed User
Looks like a bug or feature that I don't understand. Why do I get the wrong Value before RemoveTheSpacer works?

 

Attachments

  • Project.zip
    16.7 KB · Views: 41

Erel

B4X founder
Staff member
Licensed User
Longtime User
You are correct. My use case didn't include this feature.

Change the code to:
B4X:
Public Sub AddItem (Pnl As B4XView, Value As Object)
    Dim h As Int = Pnl.Height
    Pnl.Height = 0
    mCLV.Add(Pnl, Value)
    Dim LastItem As CLVItem = items.Get(mCLV.Size - 1)
    items.RemoveAt(mCLV.Size - 1)
    items.InsertAt(1, LastItem)
    Spacer.Height = Spacer.Height - h
    SpacerItem.Size = Spacer.Height
    LastItem.Offset = Spacer.Height
    LastItem.Panel.Top = LastItem.Offset
    Pnl.Height = h
    Pnl.Parent.Height = h
    UpdateIndices
    LastItem.Size = h
    RefreshIndex = RefreshIndex + 1
    Dim MyIndex As Int = RefreshIndex
    Sleep(30)
    If MyIndex = RefreshIndex Then
        mCLV.Refresh
    End If
End Sub

Private Sub UpdateIndices
    For i = 1 To items.Size - 1
        Dim item As CLVItem = items.Get(i)
        item.Panel.Tag = i 
    Next
End Sub
 
Top