Android Question CheckBox ThreeState Indetermine

zed

Well-Known Member
Licensed User
Yes, it is possible in B4J to have a checkbox with three states, including an indeterminate (or "greyed out") state.
This relies on the use of the CheckBox component of JavaFX, which supports a mode called "tri-state".
b4x:
Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
    Private cb As CheckBox
    Private fxCB As JavaObject
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MainForm.RootPane.LoadLayout("Main")
    MainForm.Show

    ' Access to native JavaFX CheckBox
    fxCB = cb
    fxCB.RunMethod("setAllowIndeterminate", Array(True))
    fxCB.RunMethod("setIndeterminate", Array(True)) ' Initial state: undetermined
End Sub

Sub cb_MouseClicked (EventData As MouseEvent)
    Dim isIndeterminate As Boolean = fxCB.RunMethod("isIndeterminate", Null)
    Dim isSelected As Boolean = cb.Checked

    ' Switch between the three states
    If isIndeterminate Then
        fxCB.RunMethod("setIndeterminate", Array(False))
        cb.Checked = True
    Else If isSelected Then
        cb.Checked = False
    Else
        fxCB.RunMethod("setIndeterminate", Array(True))
    End If
End Sub


This code has not been tested
 
Upvote 0

vinpolins

Member
Yes, it is possible in B4J to have a checkbox with three states, including an indeterminate (or "greyed out") state.
This relies on the use of the CheckBox component of JavaFX, which supports a mode called "tri-state".
...
Thank you for the answer.

How about B4A? Is it also supported?
 
Upvote 0

zed

Well-Known Member
Licensed User
Sorry, I didn't notice that it's in b4a.
Here is a b4a version.
B4A:
Private CheckState As Int = 0 ' 0 = undetermined, 1 = checked, 2 = unchecked
Private CheckBox1 As CheckBox
....
....
Private Sub CheckBox1_CheckedChange(Checked As Boolean)
    CheckState = (CheckState + 1) Mod 3
    Select CheckState
        Case 0
            CheckBox1.Checked = False
            CheckBox1.Text = "Undetermined"
            CheckBox1.Color = Colors.Gray ' To visually indicate
        Case 1
            CheckBox1.Checked = True
            CheckBox1.Text = "Checked"
            CheckBox1.Color = Colors.Green
        Case 2
            CheckBox1.Checked = False
            CheckBox1.Text = "Unchecked"
            CheckBox1.Color = Colors.Red
    End Select
End Sub
 
Upvote 0

vinpolins

Member
Sorry, I didn't notice that it's in b4a.
Here is a b4a version.
Thank you!

Is there a way not to change the background (CheckBox1.Color), but to change the visuality of the check-box instead?
(similar in Windows)

I've found the way to change the checkbox color using setButtonTintList.

B4X:
   States(0, 0) = sd.State_Checked
   States(1, 0) = sd.State_Unchecked
   Dim Color(2) As Int = Array As Int(Colors.Gray, Colors.DarkGray)

But I don't know how to get the default color of that checkbox to restore to the default state?
Any suggestion?
 
Upvote 0

zed

Well-Known Member
Licensed User
 
Upvote 0

vinpolins

Member
I've seen this, as well as the AS_CheckBoxAdvanced, but unfortunately I did not find it useful for my case.
 
Upvote 0

zed

Well-Known Member
Licensed User
If you want to change the appearance of the checkbox in B4A using JavaObject, you can access native Android properties not directly exposed by B4A.
Here's an example to change the color of the shell itself (the "check mark") without affecting the background
JavaObject:
Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1
    Root.LoadLayout("MainPage")
        
    Dim jo As JavaObject =    CheckBox1
    ' Change the color of the check mark
    jo.RunMethod("setButtonTintList", Array As Object(CreateColorStateList(Colors.Red)))

    
End Sub

Sub CreateColorStateList(Color As Int) As Object
    Dim states(1,1) As Int
    states(0,0) = 16842910 'android.R.attr.state_enabled
    Dim mColors() As Int = Array As Int(Color)
    Dim jo As JavaObject
    jo.InitializeStatic("android.content.res.ColorStateList")
    Return jo.RunMethod("valueOf", Array(mColors(0)))
End Sub

CheckBoxColor.png
 
Upvote 0

zed

Well-Known Member
Licensed User
If you want a completely different style (e.g. an icon instead of the standard box), you can replace the CheckBox with an ImageView + Label, and manage the state manually.
B4A:
Sub ImageView1_Click
    isChecked = Not(isChecked)
    If isChecked Then
        ImageView1.Bitmap = LoadBitmap(File.DirAssets, "checked.png")
    Else
        ImageView1.Bitmap = LoadBitmap(File.DirAssets, "unchecked.png")
    End If
End Sub

and use a CSBuilder to style the text

B4A:
Dim cs As CSBuilder
cs.Initialize.Color(Colors.Blue).Typeface(Typeface.SERIF).Append("Accept the conditions").PopAll
CheckBox1.Text = cs
CheckBoxColor2.png
 
Upvote 0

Mehrzad238

Active Member
If you want to change the appearance of the checkbox in B4A using JavaObject, you can access native Android properties not directly exposed by B4A.
Here's an example to change the color of the shell itself (the "check mark") without affecting the background
JavaObject:
Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1
    Root.LoadLayout("MainPage")
       
    Dim jo As JavaObject =    CheckBox1
    ' Change the color of the check mark
    jo.RunMethod("setButtonTintList", Array As Object(CreateColorStateList(Colors.Red)))

   
End Sub

Sub CreateColorStateList(Color As Int) As Object
    Dim states(1,1) As Int
    states(0,0) = 16842910 'android.R.attr.state_enabled
    Dim mColors() As Int = Array As Int(Color)
    Dim jo As JavaObject
    jo.InitializeStatic("android.content.res.ColorStateList")
    Return jo.RunMethod("valueOf", Array(mColors(0)))
End Sub

View attachment 166315
A question: can we make the square round like a circle?
 
Upvote 0

vinpolins

Member
If you want to change the appearance of the checkbox in B4A using JavaObject, you can access native Android properties not directly exposed by B4A.
Here's an example to change the color of the shell itself (the "check mark") without affecting the background
JavaObject:
Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1
    Root.LoadLayout("MainPage")
       
    Dim jo As JavaObject =    CheckBox1
    ' Change the color of the check mark
    jo.RunMethod("setButtonTintList", Array As Object(CreateColorStateList(Colors.Red)))

   
End Sub

Sub CreateColorStateList(Color As Int) As Object
    Dim states(1,1) As Int
    states(0,0) = 16842910 'android.R.attr.state_enabled
    Dim mColors() As Int = Array As Int(Color)
    Dim jo As JavaObject
    jo.InitializeStatic("android.content.res.ColorStateList")
    Return jo.RunMethod("valueOf", Array(mColors(0)))
End Sub

View attachment 166315
Actually, in the previous post, I've mentioned that I already know how to change the color of the checkmark, with the following code:

B4X:
   States(0, 0) = sd.State_Checked
   States(1, 0) = sd.State_Unchecked
   Dim Color(2) As Int = Array As Int(Colors.Gray, Colors.DarkGray)

My questions was, how to obtain the "default" color of the checkmark, so that I can restore to the default state (color)?
 
Upvote 0

zed

Well-Known Member
Licensed User
Simply pass it a null value.
JavaObject:
Dim jo As JavaObject = CheckBox1
jo.RunMethod("setButtonTintList", Array As Object(Null))

A question: can we make the square round like a circle?
You can wrap your CheckBox in a Panel or use a Label with a custom background.
This gives a round visual effect, even though the CheckBox itself remains square inside.

B4A does not allow you to directly modify the checkmark drawable without using Java code or an external library.
The checkmark is defined by the Android system. To make it round, you need to change the drawable used by the CheckBox.
This requires creating an XML file in /res/drawable with a custom circle and using a JavaObject to apply this drawable.

Or simply use an image. See #11
 
Upvote 0

vinpolins

Member
Simply pass it a null value.
JavaObject:
Dim jo As JavaObject = CheckBox1
jo.RunMethod("setButtonTintList", Array As Object(Null))
I tried the above code but it has no effect (the checkbox appearance didn't change).
Maybe something I've missed?

I used the following code to change the checkbox appearance, it works OK.
B4X:
    Dim States(2, 1) As Int
    Dim SLD As StateListDrawable
    SLD.Initialize
    States(0, 0) = SLD.State_Checked
    States(1, 0) = SLD.State_Unchecked
    Dim Color(2) As Int = Array As Int(Colors.Gray, Colors.DarkGray)
    Dim CSL As JavaObject
    CSL.InitializeNewInstance("android.content.res.ColorStateList", Array(States, Color))
    Dim CBC As JavaObject = CheckBox1
    CBC.RunMethod("setButtonTintList", Array(CSL))

And then I used the code you suggested to restore the appearance to default state, but it has no effect.
B4X:
    Dim jo As JavaObject = CheckBox1
    jo.RunMethod("setButtonTintList", Array As Object(Null))

Any ideas?
 
Upvote 0

vinpolins

Member
?
That looks good but I didn't see any code example in the given link
 
Upvote 0
Top