Android Question B4X Custom Time Dialog

RichardN

Well-Known Member
Licensed User
Longtime User
I am trying to create a dialog where the user can select a time interval Hours 0-20 and minutes 0 to 55 in 5 minute intervals.

I have something like a B4i picker in mind that accepts gestures but without the transparency of the non-selected items. I thought about two Listviews side by side only one cell high. Sadly the cells do not 'latch' to show only one line, often stopping midway between two. Is it possible to make the standard Listview centre to the nearest cell in view after input?

The standard Android spinner allows a very positive user selection but with 21/13 possible selections the drop-downs extend well outside a reasonable sized dialog giving a poor visual result.

Any suggestions?
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
1. You should never use the standard ListView. Use xCustomListView instead.
2. A simple time selection feature is included in B4XPreferencesDialog



3. You can use SnapCLV to make the items "snap". Items will be snapped to the top. If the items are with the same height then it might be good enough. Otherwise, you will need to modify the class and make them snap to a different point.
 
Upvote 0

TILogistic

Expert
Licensed User
Longtime User
tip see:
 
Upvote 0

RichardN

Well-Known Member
Licensed User
Longtime User
Hi @oparra..... Some good suggestions. I particularly like the look of the clsWheel class it is a very attractive interface, I may use it elsewhere.

I am not looking for (yet another) date/time picker for a couple of reasons. Firstly I find working with Android date/time dialogues and ticks to be far too cumbersome. Sure there are occasions where you need to input and store absolute values of date/time but using the system dialogues to harvest (and store) time intervals rather than absolute dates/times is a pain in the neck. Most of my applications only deal in hours & minutes and don't need to store absolute values. It is for that reason I am aiming for something smart but simple.
 
Upvote 0

TILogistic

Expert
Licensed User
Longtime User
Some good suggestions. I particularly like the look of the clsWheel class it is a very attractive interface, I may use it elsewhere.
You should send this question to the author of the class, who is @klaus .

Just modify that class for my needs.


As for the suggestion that I recommend, it is because it is easy to modify and is similar to what @Erel recommends.


P.S. What I recommend you can use in the designer or through a dialog. As you wish.
 
Upvote 0

RichardN

Well-Known Member
Licensed User
Longtime User
In experimentation, the xCustomListView incorporated within a B4X dialogue is visually pleasing but of course you need two CLV for the hours & minutes values.

This raises the problem of needing two different instances of SnapCLV to handle the two views. My desired end-game here would have been to have a single class module that handled ShowDialog, CLV snapping, show default values and return user values. With the required class complexity this ambition looks rather unlikely.

If only we could set xCustomListView.Snap = True. I will put that on my wish list
 
Upvote 0

RichardN

Well-Known Member
Licensed User
Longtime User
@Erel... It means I can't incorporate the SnapCLV code into the main module for single use, the code has to remain in a class. This defeats my goal of having the simplicity of a reusable dialog in a single class
 
Upvote 0

Mahares

Expert
Licensed User
Longtime User
It means I can't incorporate the SnapCLV code into the main module for single use
Yes, you can. Here is the full SnapCLV example using B4XPages where I incorporated the code from Erel's class into the main body of B4XMainPage. If you want to run it, just use the same layout Erel used in his example:
B4X:
Sub Class_Globals
    Private Root As B4XView
    Private xui As XUI
    Private CustomListView1 As CustomListView
    Private xui As XUI
    Public ScrollChangedIndex As Int
    Private InactiveDuration As Int = 200
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("1")  'use the same layout as what Erel has in the SnapCLV example
    For i = 1 To 50
        Dim p As B4XView = xui.CreatePanel("")
        p.Color = Rnd(0xff000000, 0xffffffff)
        p.SetLayoutAnimated(0, 0, 0, CustomListView1.AsView.Width, Rnd(200dip, 300dip))
        CustomListView1.Add(p, "")
    Next
End Sub

Sub CustomListView1_ScrollChanged (Offset As Int)
    ScrollChanged (Offset)
End Sub

Public Sub ScrollChanged (Offset As Int)
    ScrollChangedIndex = ScrollChangedIndex + 1
    Dim MyIndex As Int = ScrollChangedIndex
    Sleep(InactiveDuration)
    If ScrollChangedIndex = MyIndex Then
        SnapCLV(Offset)
    End If
End Sub

Private Sub SnapCLV (Offset As Int)
    Dim i As Int = CustomListView1.FirstVisibleIndex
    If i < 0 Then Return
    If Offset + CustomListView1.sv.Height >= CustomListView1.sv.ScrollViewContentHeight Then Return
    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 If
End Sub
 
Upvote 0

RichardN

Well-Known Member
Licensed User
Longtime User
Thanks @Mahares... I take your point

My issue was that you needed multiple instances of SnapCLV where you have multiple CustomListViews. I have modified the code slightly to remove the SnapCLV class AND work with multiple CustomListViews.

B4X:
'The SnapCLV Class is no longer in the project'

Sub Globals
    
    Private clvHours As CustomListView
    Private clvMinutes As CustomListView
    
    Private ScrollChangedIndex As Int
    Private Const InactiveDuration As Int = 200
    
End Sub


Sub clvHours_ScrollChanged (Offset As Int)
    ScrollChanged(clvHours,Offset)
End Sub


Sub clvMinutes_ScrollChanged (Offset As Int)
    ScrollChanged(clvMinutes,Offset)
End Sub


Public Sub ScrollChanged (SubjectView As CustomListView, Offset As Int)
    
    ScrollChangedIndex = ScrollChangedIndex + 1
    Dim MyIndex As Int = ScrollChangedIndex
    Sleep(InactiveDuration)                       
    If ScrollChangedIndex = MyIndex Then
        
        Dim i As Int = SubjectView.FirstVisibleIndex
        If i < 0 Then Return
        If Offset + SubjectView.sv.Height >= SubjectView.sv.ScrollViewContentHeight Then Return
        Dim item As CLVItem = SubjectView.GetRawListItem(i)
        Dim visiblepart As Int = item.Offset + item.Size - Offset
        
        If visiblepart / item.Size > 0.5 Then
            SubjectView.ScrollToItem(i)
        Else
            SubjectView.ScrollToItem(i + 1)
        End If
        
    End If
    
End Sub
 
Upvote 0

Mahares

Expert
Licensed User
Longtime User
work with multiple CustomListViews.
Rich, You can slightly improve your code by giving all your xCustomListViews the same event name and use the sender. In this case xClv is the common event.
B4X:
Sub xClv_ScrollChanged (Offset As Int)
    ScrollChanged(Sender,Offset)
End Sub
 
Upvote 1
Cookies are required to use this site. You must accept them to continue using the site. Learn more…