B4J Question Drag CustomListView up and down using mouse click

aeric

Expert
Licensed User
Longtime User
I think I need to modify CustomListView to support this feature.
I want to drag the panel like a ScrollPane.
Maybe someone already have a solution?
 

aeric

Expert
Licensed User
Longtime User
Move

On left side, ScrollPane can be move up or down using mouse click and hold.
On right side, CLV is not supported but as far as I know CLV is actually also a ScrollPane.
 

Attachments

  • Example.zip
    4.5 KB · Views: 33
Upvote 0

PaulMeuris

Well-Known Member
Licensed User
I have added a CLVDragger class to your example.
The CLVDragger class adds drag buttons on each item.
Click and drag the button to drag the panel up or down.
Clicking on the panel and not the drag button will trigger the CustomListView1_ItemClick event.
You can maybe modify the size of the drag button to have a bigger surface to click and drag on...
 

Attachments

  • Aeric_Example3_paul.zip
    6 KB · Views: 29
Upvote 0

aeric

Expert
Licensed User
Longtime User
I have added a CLVDragger class to your example.
The CLVDragger class adds drag buttons on each item.
Click and drag the button to drag the panel up or down.
Clicking on the panel and not the drag button will trigger the CustomListView1_ItemClick event.
You can maybe modify the size of the drag button to have a bigger surface to click and drag on...
Thanks Paul but I think you didn't get what I try to achieve.
I will try to create a video to show what I mean.
 
Upvote 0

stevel05

Expert
Licensed User
Longtime User
The biggest problem is that while clv is indeed on a scrollpane, All of the views in the layout will consume the mouse events before they get to the ScrollPane.

To have any chance of it working, you would need to add an eventfilter (processed before the event handlers) to the scrollpane to capture the Mouse event, probably mouse_dragged, and then calculate the required scroll and apply it manually.
 
Upvote 0

aeric

Expert
Licensed User
Longtime User
Thanks Steve.
I have tried using Reflector to add eventfilter but not succeed to fire the mouse events.
I don't need click events for individual list item.
How about adding a transparent layer on top and set the height to total height of list items?
 
Upvote 0

aeric

Expert
Licensed User
Longtime User
Improved mouse pressed and released cursor changes.

scroll3-ezgif.com.gif
 

Attachments

  • Example3.zip
    4.3 KB · Views: 22
Upvote 0

aeric

Expert
Licensed User
Longtime User
One thing missing is mouse scroll inside the panel. It's okay, I can use the scrollbar.
 
Upvote 0

aeric

Expert
Licensed User
Longtime User
Handle resize

B4X:
Private Sub B4XPage_Resize (Width As Int, Height As Int)
    DragPane.SetSize(CustomListView1.AsView.Width - 18dip, CustomListView1.AsView.Height)
End Sub
 
Upvote 0

aeric

Expert
Licensed User
Longtime User
Should this enhancement integrated into the CustomListView?
Maybe introduce a new property to enable/disable this feature.
 
Upvote 0

PaulMeuris

Well-Known Member
Licensed User
It is clear to me now what you want to do.
@aeric Can you elaborate on the use case where you don't want the user to click on an item?
To compare both solutions i have added some code to fill the ScrollPane.
@stevel05 If you click on the first item in the CustomListView the following error occurs:
java.lang.NullPointerException: Cannot invoke "Object.equals(Object)" because the return value of "anywheresoftware.b4j.objects.ScrollPaneWrapper.getMouseCursor()" is null
My preference goes to the first solution with the panel and the ScrollView (and the items list).
The first solution doesn't require to code the events, they are already present!
 

Attachments

  • CLVMouseScroll2_paul.zip
    5.3 KB · Views: 26
Upvote 1

aeric

Expert
Licensed User
Longtime User
Here is a refactored version from Steve code above which I modified from ChatGPT.

B4X:
Sub Class_Globals
    Private Root As B4XView
    Private xui As XUI
    Private Pane1 As Pane
    Private ScrollPane1 As ScrollPane
    Private CustomListView1 As CustomListView
    Private DragSceneY As Double
    Private SBV As JavaObject
    Private fx As JFX
End Sub

Public Sub Initialize
'    B4XPages.GetManager.LogEvents = True
End Sub

' This event will be called once, before the page becomes visible.
Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1
    Root.LoadLayout("MainPage")
    ScrollPane1.LoadLayout("ListItem1", ScrollPane1.As(B4XView).Width - 20dip, ScrollPane1.As(B4XView).Height)
    Pane1.PrefHeight = 800dip
    ScrollPane1.As(B4XView).ScrollViewInnerPanel.Height = Pane1.PrefHeight
    'Add some example list items
    For i = 1 To 4
        CustomListView1.Add(CreateListItem(CustomListView1.AsView.Width, 400dip), i)
    Next  
    EnableDragScroll(CustomListView1)
End Sub

Private Sub CreateListItem (Width As Int, Height As Int) As B4XView
    Dim p As B4XView = xui.CreatePanel("")
    p.LoadLayout("ListItem1")
    p.SetLayoutAnimated(0, 0, 0, Width, Height)
    Return p
End Sub

' Enable click-and-drag scrolling for a CustomListView
Private Sub EnableDragScroll (clv As CustomListView)
    Dim spJO As JavaObject = clv.sv
    'Attach all event filters in one go
    AddEventFilter(spJO, "MOUSE_PRESSED", "SPPressed")
    AddEventFilter(spJO, "MOUSE_RELEASED", "SPReleased")
    AddEventFilter(spJO, "MOUSE_DRAGGED", "SPDragged")
    'Cache the vertical scrollbar for later calculations
    Sleep(0) ' wait for UI to build
    SBV = GetScrollBar(spJO, "VERTICAL")
End Sub

' Utility to attach JavaFX event filters
Private Sub AddEventFilter (target As JavaObject, eventName As String, handlerName As String)
    Dim Eventhandler As Object = target.CreateEvent("javafx.event.EventHandler", handlerName, Null)
    Dim MouseEvent As JavaObject
    MouseEvent.InitializeStatic("javafx.scene.input.MouseEvent")
    target.RunMethod("addEventFilter", Array(MouseEvent.GetField(eventName), Eventhandler))
End Sub

' Event Handlers
Private Sub SPPressed_Event (MethodName As String, Args() As Object)
    Dim Event As JavaObject = Args(0)
    DragSceneY = Event.RunMethod("getY", Null)
End Sub

Private Sub SPReleased_Event (MethodName As String, Args() As Object)
    Dim SP As ScrollPane = Sender
    If SP.MouseCursor = fx.Cursors.MOVE Then SP.MouseCursor = fx.Cursors.DEFAULT
End Sub

Private Sub SPDragged_Event (MethodName As String, Args() As Object)
    Dim SP As ScrollPane = Sender
    SP.MouseCursor = fx.Cursors.MOVE
    Dim Event As JavaObject = Args(0)
    Dim ThisY As Double = Event.RunMethod("getY", Null)
    Dim contentHeight As Double = SP.InnerNode.PrefHeight
    Dim visibleHeight As Double = SBV.RunMethod("getVisibleAmount", Null) * contentHeight
    SP.VPosition = SP.VPosition + (DragSceneY - ThisY) / (contentHeight - visibleHeight)
    DragSceneY = ThisY
End Sub

' Utility to get a ScrollBar JavaObject
Public Sub GetScrollBar (Node As JavaObject, Orientation As String) As JavaObject
    Dim SBSet As JavaObject = Node.RunMethod("lookupAll", Array(".scroll-bar"))
    Dim Iterator As JavaObject = SBSet.RunMethod("iterator", Null)
    Do While Iterator.RunMethod("hasNext", Null)
        Dim SB As JavaObject = Iterator.RunMethod("next", Null)
        Dim SBOrientation As String = SB.RunMethodJO("getOrientation", Null).RunMethod("toString", Null)
        If SBOrientation = Orientation.ToUpperCase Then Return SB
    Loop
    Return SB 'Null
End Sub
 
Last edited:
Upvote 0

aeric

Expert
Licensed User
Longtime User
My preference goes to the first solution with the panel and the ScrollView (and the items list).
The first solution doesn't require to code the events, they are already present!
Yes, currently in my POS system, I am using ScrollPane ("ScrollView" for B4J) where I have a layout for the inner panel contains a panel and a label.
It is a bit troublesome to calculate the height and handling different layouts. It is also difficult to format the label style or size.
I am trying to migrate to CLV which provide user the flexibility to customize the receipt template.
 
Upvote 0

aeric

Expert
Licensed User
Longtime User
Thanks both @PaulMeuris and @stevel05
My problem is I am lack of understanding on how to use ScrollPane and CustomListView.
Now I have 2 options to solve my problem.
 
Upvote 0
Top