B4A Library [Class]ClsWheel Input wheels

Attached you find a new CLASS ClsWheel.

It allows to display different data input screens with wheels.

What can be done ?
You can define nine different types of Wheel input screens:
  • DATE a date input : year / month / day
    A default value can be defined or Now, the current date.
    The returned value has the current DateFormat.
  • TIME_HM a time input : hour / minute
    A default value can be defined or Now, the current time.
    The returned value has the current TimeFormat.
  • TIME_HMS a time input : hour / minute / second
    A default value can be defined or Now, the current time.
    The returned value has the current TimeFormat.
  • DATE_TIME a date + time input : year / month / day / hour / minute
    A default value can be defined or Now, the current date and time.
    The returned value has the current DateFormat and TimeFormat.
  • CUSTOM a custom input with user defined input values.
    The number of side by side wheels is user defined (max. 5 wheels).
    A default value can be defined.
    A specific separation character can be defined, a blanc character is default.
  • INTEGER positive and negative integers
  • INTEGER_POS only positive integers
  • NUMBER positive and negative numbers
  • NUMBER_POS only positive numbers
Main functions:
Initialize initializes the wheel class Note: the Initialize routine hasone more parameter cContinusScrolling As Boolean (since version 1.3) .
Example :
whlDate.Initialize(Me, Activity, "Enter date", 3, Null, 24, 0, True)
Me = calling module, the current
Activity =
Enter date = title of the input
3 = number of wheels, this number is used only for CUSTOM input types
Null = no input data, set internally
24 = text size
0 = DATE input type
True = continus scrolling

Show show the input wheel(s)
Example :
whlDate.Show(lblSelection, "11/22/2001")
lblSelection = Label which gets the result
11/22/2001 = Default value to preset the wheels

Show2 show the input wheel(s)
Example :
whlCustum.Show2("whlCustom", "")
"whlCustom" = EventName
"" = no default value
The event is called 'Closed'.
The event routine in the calling module, for the example, must be
Sub whlCustom_Closed(Canceled As Boolean, Selection As String)

The width and height are defined by the program according to the font size.

If the width or the height exceed the screen width or height the font size is downscaled.

You can change most of the colors.

Needs the Reflection library.

Bug reports and suggestions are welcome.

I hope that the code is enough self explanatory, but if you want more explanations I can add them.
Anyway the best way to know what can be done is to test it.

PS. There is no logic in the custom input screen just to demonstrate the possibility.

Best regards.


EDIT: 2020.11.25 Version 2.7
Amended warning in line 946: Comparison of Object to other types will fail if exact types do not match.
EDIT: 2015.04.29 Version 2.0
Added a Tag property

EDIT: 2017.06.27 Version 2.6
Replaced DoEvents by Sleep(0)
Needs B4A version 7.00+

EDIT: 2017.03.30 Version 2.5
Amended the wish expressed HERE
Different font sizes for title and wheels.
With long titles, the font size of both, title and wheels, was reduced.
Now only the title font size is reduced.

EDIT: 2017.03.28 Version 2.4
Amended the error reported HERE
Problem with +/- in number wheels

EDIT: 2015.09.22 Version 2.3
Amended the error reported in post #185

EDIT: 2015.05.10 Version 2.2
Amended the variable declaration problem reported in post #175

EDIT: 2015.05.10 Version 2.1
Amended the timer problem reported in post #170

EDIT: 2014.09.09 Version 1.9
Added number wheels INTEGER, INTEGER_POS, NUMBER, NUMBER_POS wheels
Amended day scroll problem reported in post #141

EDIT: 2014.04.21 Version 1.7
Amended OutOfMemory problem reported HERE.

EDIT: 2013.09.15 Version 1.6
Added min MinYear and NumberOfYears properties to adapt the years to select

EDIT: 2013.08.08 Version 1.5
Added StartScroll and EdnScroll events

EDIT: 2013.06.14 Version 1.4
Modified OK event to Closed event post#37
Amended screen color problem post#36
Amendet getSeparationText error post #41

EDIT: 2013.06.12 Version 1.3
Mofied property routines.
Added Show2 for raising an event when clicking the OK button
Added optional continus scrolling

EDIT: 2013.05.28 Version 1.2
Amended the bug reported in post #32

EDIT: 2012.12.15 Version 1.1
Amended the reported bugs.
 

Attachments

  • Time_input.jpg
    Time_input.jpg
    32.9 KB · Views: 2,283
  • Custom_input.jpg
    Custom_input.jpg
    45.3 KB · Views: 2,201
  • ClsWheelV2_5.zip
    19.1 KB · Views: 481
  • ClsWheelV2_7.zip
    19.3 KB · Views: 501
Last edited:

cimperia

Active Member
Licensed User
Longtime User
Hi Klaus,

I am using this in a project - thank you very much for this pretty wheel.

I have two suggestions:

Would it be possible to add a Tag object to the Class?

I would like to be able to use the INTEGER (and maybe NUMBER) wheel types with start and end numbers. As cWheelContent is not used when initializing these wheel types, it could be used to store the values? Little change would be required: if the cWheelContent list is not initialized then the wheel is populated as now (0 to 9), otherwise the values stored in the list would be used.

It would be nice to have at least the Tag property as standard.

Cheers
Claudio
 

cimperia

Active Member
Licensed User
Longtime User
Thanks Klaus, that was quick response time!

About the second point: when one initializes a wheel of type INTEGER_POS (6) for example:

B4X:
   whlInteger.Initialize(Me, Activity, "Enter integer", 4, Null, 24, 5, False)

if I am not mistaken, the method InitializeNumbers gets called and populates the wheel with digits from 0 to 9.

I would like the ability to send start and end numbers in cWheelContent list parameter, for example {15, 80}, therefore limiting the range of possible choices.

I realize that the way the class is designed is such that a number is a combination of multiple wheels for units, tens etc..., but this would not make any difference. If I were to define a single wheel.

At the moment, if I want such an object, I have populate a list with the values and they are interpreted as string by the Class, and initialize a Custom Wheel.

My use case is simple: I want to replace some SeekBars, that some users find difficult to handle, with your Class as it is so much easier.

I don't know whether this would integrate naturally in your class or not.

After giving this a bit more thought, maybe adding a RANGE_WHEEL, where the list parameter (cWheelContent) would contain the type (INTEGER etc...), ex {6, 15, 80} would be cleaner.

What are your thoughts?
 
Last edited:

cimperia

Active Member
Licensed User
Longtime User
I forgot to mention that as part of the info conveyed in cWheelContent, an increment or step would be great. It could be 1, 2 etc. for Int, or 0.2, 0.5 ... for Real numbers, ex {6, 2, 10, 80}
 

klaus

Expert
Licensed User
Longtime User
Introducing limit numbers wouldn't be easy.
Because you need to update some wheels according to the choices of other wheels.
In your example with min 15 and max 80.
The first wheel will be limited between 1 and 8, no problem.
But for the second wheel you must limit it between 5 and 9 if the first wheel is 1.
If the first wheel is set to 8 the second wheel must be limited to 0 only.
For all other values, from 2 to 7, in the first wheel the second wheel will be set from 0 to 9.
If the second wheel is 0 and the user changes the first wheel and it reaches 1 you need to set the second one between 5 and 9 and jump it to 5.
All this checking and clearing and refilling the wheels is not that easy.
This kind of checking is done in the date wheel for the days depending on the selected month, but in this case it's only for one wheel.

I added the number wheels because there was a request and it was challanging for me, but I would never use a wheel to enter a number. I would use an EditText and a specific keyboard. I used this in the DynSim program.
For me this is a much more efficient user interface than a wheel.
Even in the Android Agenda when I enter a new appointment I get bored when I have to move the minute wheel.

Anyway the source code is open source, so feel free to adapt it to your needs.
 

cimperia

Active Member
Licensed User
Longtime User
Thank you for your answer.

No problem, I understand, though I did not suggest the use of multiple wheels, but just the one where a single wheel contains all the values from say 15 to 60, it's like a custom wheel if you wish.

I shall code it myself as you have generously opened the source :)
 

cimperia

Active Member
Licensed User
Longtime User
It's actually very easy, as your Class is easy on the eye and it contains all I need.

Yes I have created a new type:

B4X:
    Public NUMBER_RANGE = 9 As Int

I've started coding it.

The parameter cWheelContent will contain these entries for the wheel:{numericType, incrementSize, lowLimt, topLimit}, ex. {6, 2, 10, 80}
To start with, I'll allow for only the one wheel for this object.

Later, it should not be difficult to extend to multiple wheels (I actually want 2 to simulate a RangeSeekBar), as cWheelContent will contain multiples of {numericType, stepSize, lowLimt, topLimit} values.

I'd rather use a Type, but as they are always public, I won't.

Thank you for the pointers.
 

cimperia

Active Member
Licensed User
Longtime User
I have noticed an issue with the current class. If you have 2 wheels say, and you spin one and immediately spins the other, if continuous scrolling is set to True, then the wheel spun first will not refresh properly. See attached image.

I have finished coding what I required. I have actually introduced only a new type INTEGER_POS_RANGE and it can handle multiple wheels, though I have limited it to 2.

The parameter cWheelContent will contain these entries for the wheel:{incrementSize, lowLimt, topLimit}, ex. {2, 10, 80}

B4X:
Sub Activity_Resume
   Activity.LoadLayout("main") 
   InitWheelDataRange
End Sub

Sub InitWheelDataRange
   Dim NumberList(2) As List
   NumberList(0).Initialize
   NumberList(0).AddAll(Array As String("3", "4", "28"))
   'Increment size
   'Lower Limit
   'Higher Limit
  '
   NumberList(1).Initialize
   NumberList(1).Add("2")
   NumberList(1).Add("0")
   NumberList(1).Add("13")

   whlIntRange.Initialize(Me, Panel1, "Pick a No", 2, NumberList, 18, 9, True)
   whlIntRange.SetSeparationText(" ")
   whlIntRange.TitleTextColor = Colors.Magenta
End Sub

Sub btnSelectCustom_Click
   whlIntRange.Show(lblShowSelection, lblShowSelection.Text )
'   whlIntRange.Show2("whlIntRange", "22 4")
End Sub
 

Attachments

  • ClsWheelIssue.png
    ClsWheelIssue.png
    27.1 KB · Views: 233
Last edited:

cimperia

Active Member
Licensed User
Longtime User
Regarding the bug reported in my previous post, i.e. if two or more wheels, which belong to the same group, for example INTEGERS, are spun at the same time, some of the wheels do not get refreshed properly .

The reason is that only one timer handles the individual wheels when there should be one for each. With a few Log() calls it’s easy to see that in some cases the timer gets disabled for the wrong wheel, which therefore does not get refreshed and its EndScroll event does not get called.

Obviously reducing the Interval for the timer would also fix the issue, but we lose some of the pretty wheel effect.

An array or list of timers could be used to fix the issue.

Here’s a bit code to reveal the issue with two wheels. The code fixes the issue just as a proof of concept but requires generalization for multiple wheels and no hard-coding.
B4X:
Private Sub TimerWheel_Tick
  Dim wt As Timer = Sender
   Dim i As Int = 0
   'It is clear that timer and ScrollView do not always get matched
   'i.e. Timer(0) may get disabled for ScrollView(1)
   Select wt
     Case TimerWheel(0) : Log("Timer:0 Wheel:" & CurrentScrollView.Tag)
                          i = 0
     Case TimerWheel(1) : Log("Timer:1 Wheel:" & CurrentScrollView.Tag)
                          i = 1
   End Select
   wt.Enabled = False
   ScrollFinish(scvWheel(i), scvWheel(i).ScrollPosition)
'   ScrollFinish(CurrentScrollView, CurrentScrollView.ScrollPosition)
End SubEnd Sub
 
Last edited:

klaus

Expert
Licensed User
Longtime User
I have not yet taken the time to deeply look at this issue, but I have not missed it.
Wenn I read it, I suspected also that the problem is because I use only one timer.
These days I have some other jobs in the pipe line, but soon as I have time I will look at it.
Perhaps two timers would be enough and if not we need one timer per wheel.
 

cimperia

Active Member
Licensed User
Longtime User
OK, as I needed a quick fix on this I have edited clsWheel.bas myself while waiting for the official release. I am not saying it's the best way to go about it, and is probably not, but the logic is easy to follow and it looks robust.

An array of timers has been declared of same size as the number of wheels.

The "meat" of the fix is in the Tick Event.

I have uploaded the clsWheel file, just in case.

B4X:
Private Sub TimerWheel_Tick
   Dim wt As Timer = Sender
   For i = 0 To TimerWheel.Length - 1
     If TimerWheel(i) = wt Then
       TimerWheel(i).Enabled = False
       Exit
     End If
   Next
   ScrollFinish(scvWheel(i), scvWheel(i).ScrollPosition)
End Sub
 

Attachments

  • ClsWheel.zip
    7.9 KB · Views: 225

yashwant

Member
Licensed User
Longtime User
Hello Klaus

I am trying to run the project attached in the first post

I m getting following Error

B4A version: 5.02 (1)
Parsing code. (0.10s)
Compiling code. Error
Error compiling program.
Error description: Current declaration does not match previous one.
Make sure to declare the variable before it is used in a For loop.
Occurred on line: 179
Dim i, j As Int
Word: ,


Any thing that I am missing ...


Yashwant
 

yashwant

Member
Licensed User
Longtime User
Thanks Klaus, that was quick response time!

Again thank you very much for this pretty wheel


Best Regards
Yashwant
 

Espinosa4

Active Member
Licensed User
Longtime User
Hi everyone!
I am using this class and I have some graphical problems in android 5.

Can you help me, please?
Thank you very much in advance!

Here the capture.
The buttons are on the background
 

Attachments

  • Screenshot (28-8-2015 10-41-31).png
    Screenshot (28-8-2015 10-41-31).png
    136.8 KB · Views: 215

klaus

Expert
Licensed User
Longtime User
The buttons are on the background
Are you sure ?
The Wheel class is on a panel filling the whole screen which is semi-transparent.
When the wheel is displayed, and you click on a button, is the Click event fired ?
If yes, means that the buttons are not in the background.
 
Top