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