Android Question How to Determine the Index of the closest Item to the Center of an xClv

Mahares

Expert
Licensed User
Longtime User
How do you determine the index of the closest item to the center of an xClv in Sub xClv_VisibleRangeChanged (FirstIndex As Int, LastIndex As Int) after a scroll is stopped. I am looking for the center item index among the displayed items on the screen whether vertical or horizontal xClv
Thank you
 

Mahares

Expert
Licensed User
Longtime User
I think it should be: Floor(FirstIndex + LastIndex) / 2 to prevent decimal indices. But my remark is trivial. The problem is: While the xClv is scrolling, you get many center indices. I am intereted in the last index when the scrolling stopped. I am trying to see if Sub xclv_ScrollChanged (Offset As Int) can provide me with that or if there is a more obvious answer.
Thank you
 
Upvote 0

William Lancee

Well-Known Member
Licensed User
Longtime User
I see. The offset solution will not work if your items are not equal height or if small errors creep in.
I would probably use a global Private LastCenterIndex As Int, set it by (FirstIndex + LastIndex) / 2 in VisibleRangeChanged and look at it
in ScrollChanged. Just a thought.
 
Upvote 0

Mahares

Expert
Licensed User
Longtime User
Yes. I had it as global
Private CenterIndex As Int 'in global
CenterIndex =Floor(FirstIndex + LastIndex) / 2

This sub is lacking something. Not sure what to use for offset here
B4X:
Sub xclv_ScrollChanged (Offset As Int)
    ScrollChangedIndex = ScrollChangedIndex + 1
    Dim MyIndex As Int = ScrollChangedIndex
    If ScrollChangedIndex = MyIndex Then
        Log("Center: " & CenterIndex)
    End If    
End Sub
 
Upvote 0

William Lancee

Well-Known Member
Licensed User
Longtime User
The missing element is Sleep.

B4X:
Private Sub CustomListView1_VisibleRangeChanged (FirstIndex As Int, LastIndex As Int)
    LastCenterIndex = (FirstIndex + LastIndex) / 2
End Sub

Private Sub CustomListView1_ScrollChanged (Offset As Int)
    ScrollChangedIndex = ScrollChangedIndex + 1
    Dim MyIndex As Int = ScrollChangedIndex
    Sleep(300)
    If MyIndex = ScrollChangedIndex Then
        Log(LastCenterIndex)
    End If
End Sub
 
Upvote 0

Mahares

Expert
Licensed User
Longtime User
he missing element is Sleep.
Yes. The Sleep() definitely helped. I was trying to use it with the CLVSnap class, which was giving me 2 colored views. So I ended up commenting the Snap line as you can see in my code:. It would be nice to keep the CLVSnap, but it is not essential. I can live without it
B4X:
Private Sub CLV1_ScrollChanged (Offset As Int)
    ScrollChangedIndex = ScrollChangedIndex + 1
    Dim MyIndex As Int = ScrollChangedIndex
'    snap.ScrollChanged(Offset)    
    Sleep(300)
    If MyIndex = ScrollChangedIndex Then
        Log(CenterIndex)
        Dim ppp As B4XView  =clv1.GetPanel(CenterIndex)
        Dim lbl As B4XView = ppp.GetView(0).GetView(0)
        lbl.SetColorAndBorder(xui.Color_Yellow, 5dip, xui.Color_Black, 5dip)
    End If
End Sub
 
Upvote 0

William Lancee

Well-Known Member
Licensed User
Longtime User
Funny you should say that. I also looked at SnapCLV.
The Class is very small, and the critical sub fits nicely with your and my code. So I used the Sub from the class in this code.

You'll note that when Snap scrolls the ScrollChanged is called again so you'll have to account for that with a Global SnapBusy.
Also note that now you don't need the global LastCenterIndex or the VisibleRangeChanged.
I did tweak the SnapCLV to force a ScrollChange when at the boundaries of the CLV.

B4X:
Private Sub LoadCLV
    For i = 0 To 99
        CustomListView1.AddTextItem("Item " & i, "")
    Next
    Log(Floor((CustomListView1.FirstVisibleIndex + CustomListView1.LastVisibleIndex) / 2))
End Sub

Private Sub CustomListView1_ScrollChanged (Offset As Int)
    ScrollChangedIndex = ScrollChangedIndex + 1
    Dim MyIndex As Int = ScrollChangedIndex
    Sleep(500)
    If MyIndex = ScrollChangedIndex Then
        If SnapBusy Then                    'SnapBusy is Global
            Log(Floor((CustomListView1.FirstVisibleIndex + CustomListView1.LastVisibleIndex) / 2))
            SnapBusy = False
        Else
            SnapBusy = True
            SnapCLV(Offset)
        End If
    End If
End Sub

Private Sub SnapCLV (Offset As Int)
    Dim i As Int = CustomListView1.FirstVisibleIndex
    If i < 0 Or (Offset + CustomListView1.sv.Height >= CustomListView1.sv.ScrollViewContentHeight) Then
        CustomListView1_ScrollChanged(Offset)
        Return
    End If
    Dim item As CLVItem     = CustomListView1.GetRawListItem(i)
    Dim visiblepart As Int = item.Offset + item.Size - Offset
    If visiblepart / item.Size > 0.5 Then CustomListView1.ScrollToItem(i) Else CustomListView1.ScrollToItem(i + 1)
End Sub
 
Upvote 0

Mahares

Expert
Licensed User
Longtime User
Funny you should say that. I also looked at SnapCLV.
Ok Willy, thank you very much. I will make a separate project with your code and see if I can apply any of it to mine. The sub I have in my post #7 does it for me. The only problem is when I resume the scrolling, that label that changed color to yellow remains yellow without reverting back to its original color and another label becomes yellow when the scrolling stops. So, in other words, I only wanted the label that I just scrolled to to change color to yellow and the others to go back to their starting state. That is what I am working on.

1678560940825.png
 
Upvote 0

William Lancee

Well-Known Member
Licensed User
Longtime User
I don't want to think I am taking over you project.
It is just that this is an interesting challenge and its Saturday, and I have time on my hands, and you are always willing to help others.

I tried a few things and I found this most pleasing with Snap. It continuously tries to keep the center yellow.
It works best with an odd number of panels on the screen.

centerYellow.gif
 

Attachments

  • scrollCenter.zip
    14.6 KB · Views: 126
Upvote 0

Mahares

Expert
Licensed User
Longtime User
this is an interesting challenge and its Saturday
Since you are more familiar with your own project, I put aside mine for now and made a project that I was going to just attach here based on your code. But I just saw your post. I will take a look at it and see it before I post anything yet on my end.
EDIT: I tested your code you have in post 10 by using some of it [n the project I made which is a vertical xClv from your code in post 8 . It looks good. Now I can go back to my project where the VisbleRange sub has a lot of stuff and try it there. Thank you. I know you like challenges; you mentioned that before. Have a good evening.
 
Last edited:
Upvote 0
Top