I'm working on creating an application, which amongst other features has an integrated GAD Test functionality (self test to calculate and measure the user's stress level). This is how it looks:
It is consisted of a Table, with multiple rows of ToggleButtons. This is the code for 1 of the buttons, as an example:
<ToggleButton
android:id="@+id/row1_btn4"
android:layout_width="200px"
android:layout_height="60dp"
android:layout_gravity="center_horizontal"
android:background="@drawable/button_border"
android:gravity="center"
android:paddingStart="10px"
android:paddingEnd="10px"
android:scaleX="0.5"
android:scaleY="0.65"
android:textColor="@color/white"
android:textOff=" "
android:textOn="✓"
android:textSize="28sp" />
and this is the code to check whether a button is checked or not:
row1_btn4.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
gadpoints += 3;
((DataSite) getActivity().getApplication()).setGadPoints(gadpoints);
} else if (!isChecked) {
gadpoints -= 3;
((DataSite) getActivity().getApplication()).setGadPoints(gadpoints);
} else {
gadpoints += 0;
((DataSite) getActivity().getApplication()).setGadPoints(gadpoints);
}
}
});
Everything is working as it should, if a ToggleButton is checked, the user is awarded the given points. However, I would like to implement 2 things:
a) Make it so that only 1 button from each row can be checked, and prevent the user from checking another one from the same row if he / she already checked 1
b) Check whether in a row of buttons none of them has been checked, and if so, notify the user
I cannot think of a feasible solution to this, because I will be essentially checking if a button hasn't been checked, but then again, some of them are meant to be unchecked. Any ideas?
You can manage having only one entry selected per row using a RadioGroup
. To start the RadioGroup
with nothing selected you can call clearCheck()
on it.
To make sure that a selection was made in all rows when they click "Submit" you can call getCheckedRadioButtonId()
on each group/row, it will return -1 if nothing was selected.
If you want to customize what the radio buttons look like there are lots of examples of how to do that here.
Here is an example of what that would look like in onCreate
:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
List<RadioGroup> rows = Arrays.asList(
findViewById(R.id.row1),
findViewById(R.id.row2)
);
// Start out with all buttons un-checked
for(RadioGroup row : rows) {
row.clearCheck();
}
// make a list of button IDs for each row to
// simplify calculating the score
List<List<Integer>> rowIds = Arrays.asList(
Arrays.asList(R.id.row1_btn1, R.id.row1_btn2, R.id.row1_btn3, R.id.row1_btn4),
Arrays.asList(R.id.row2_btn1, R.id.row2_btn2, R.id.row2_btn3, R.id.row2_btn4)
);
Button submit = findViewById(R.id.submit);
submit.setOnClickListener(v -> {
// check that all rows have selections
boolean missing_values = false;
for(RadioGroup row : rows) {
// This will be -1 if nothing was selected
if( row.getCheckedRadioButtonId() == -1 ) {
missing_values = true;
}
}
if( missing_values ) {
Toast.makeText(this, "Missing entries on some rows", Toast.LENGTH_LONG).show();
}
else {
// handle the result - add up scores or whatever is needed and send the data
// to the model
int score = 0;
for(int r = 0; r < rows.size(); ++r) {
int sel = rows.get(r).getCheckedRadioButtonId();
score += rowIds.get(r).indexOf(sel);
}
Toast.makeText(this, "All rows selected - score = " + score, Toast.LENGTH_LONG).show();
}
});
}
and the XML that goes along with it
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/row1_title"
android:text="Row 1"
android:layout_margin="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/row1"
app:layout_constraintBottom_toBottomOf="@id/row1"/>
<RadioGroup
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="@+id/row1"
android:orientation="horizontal"
app:layout_constraintStart_toEndOf="@id/row1_title"
app:layout_constraintTop_toTopOf="parent">
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/row1_btn1"/>
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/row1_btn2"/>
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/row1_btn3"/>
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/row1_btn4"/>
</RadioGroup>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/row2_title"
android:text="Row 2"
android:layout_margin="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/row2"
app:layout_constraintBottom_toBottomOf="@id/row2"/>
<RadioGroup
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="@+id/row2"
android:orientation="horizontal"
app:layout_constraintStart_toEndOf="@id/row2_title"
app:layout_constraintTop_toBottomOf="@id/row1">
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/row2_btn1"/>
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/row2_btn2"/>
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/row2_btn3"/>
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/row2_btn4"/>
</RadioGroup>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Submit"
android:id="@+id/submit"
android:layout_margin="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/row2"
/>
</androidx.constraintlayout.widget.ConstraintLayout>