I'm building a module for checking an answer in my Android java app and it doesn't work. While debugging it shows that the variable holds a value that is completely unexpected for it to hold. Could please someone explain what the problem might be? Here is the module:
private void QuizOperations() {
Toast.makeText(QuizActivity.this,"quizOperation", Toast.LENGTH_SHORT).show();
answered = true; // when the question is already answered Set bool to true
RadioButton rbSelected = findViewById(rbGroup.getCheckedRadioButtonId());
int indexofchild =rbGroup.indexOfChild(rbSelected) +1;
int answerNr = indexofchild +1;
checkSolution(answerNr,rbSelected);// method checks if the answer that is selected by the user corresponds to the answer in the database
}
The intended way was rbselected getting the index of the RadioButton pressed by the user, and than answerNr gets the index of this button as int. Than it passes in to the checksolution() function which checks if the AnswerNr corresponds to the right answer in the database. However, while debugging answerNr holds the value of 5 whichever button I press.
Debug screenshot
Let me know if any additional code needed. Thanks a lot
Here is a very minimalistic example on how to detect the view is being pressed, set/get id from tag.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:background="#333333">
<RadioButton
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:id="#+id/radioButton1"/>
<RadioButton
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:id="#+id/radioButton2"/>
<RadioButton
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:id="#+id/radioButton3"/>
</LinearLayout>
public class MainActivity extends AppCompatActivity implements View.OnClickListener
{
private String[] answers = {
"January",
"February",
"March",
};
private RadioButton rb1, rb2, rb3;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
rb1 = findViewById(R.id.radioButton1);
rb2 = findViewById(R.id.radioButton2);
rb3 = findViewById(R.id.radioButton3);
rb1.setTag("0");
rb2.setTag("1");
rb3.setTag("2");
rb1.setOnClickListener(this);
rb2.setOnClickListener(this);
rb3.setOnClickListener(this);
}
#Override
public void onClick(View view)
{
final int index = Integer.parseInt((String)view.getTag());
switch(view.getId()) {
case R.id.radioButton1:
rb2.setChecked(false);
rb3.setChecked(false);
Toast.makeText(MainActivity.this, answers[index], Toast.LENGTH_SHORT).show();
break;
case R.id.radioButton2:
rb1.setChecked(false);
rb3.setChecked(false);
Toast.makeText(MainActivity.this, answers[index], Toast.LENGTH_SHORT).show();
break;
case R.id.radioButton3:
rb1.setChecked(false);
rb2.setChecked(false);
Toast.makeText(MainActivity.this, answers[index], Toast.LENGTH_SHORT).show();
break;
}
}
}
Related
I would like to enable or disable the OK (POSITIVE) button of the AlertDialog with a custom layout such that I can:
Disable the OK button initially
Enable the OK button when all required fields have been entered
Disable the OK button again if a required field has been cleared
Perform validation after the OK button is selected and prevent dismissal upon validation errors
Assume the AlertDialog layout is as follows with one required field description and one optional field age:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<EditText
android:id="#+id/description"
android:hint="Field is required"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toTopOf="#id/age" />
<EditText
android:id="#+id/age"
android:hint="Optional"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="#id/description"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Assume I have a button to kick off the dialog
Button b = findViewById(R.id.main_button);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.e(TAG,"button");
View viewcustom = getLayoutInflater().inflate(R.layout.customdialog,null);
EditText edt1 = viewcustom.findViewById(R.id.description);
EditText edt2 = viewcustom.findViewById(R.id.age);
// render alertdialog
}
});
Here is the code. I created a custom layout with 2 EditText fields and require only 1 to be entered. The first is treated as just text that must be present and the second is treated as an optional Age. The final example shows how to add validation and to "not dismiss" after OK is pressed and validation fails.
The OK button is initially disabled and when data is entered in the first text field the OK button is enabled.
By controlling the enable/disable of the positive (OK) button it requires the user to the enter fields necessary (rather than giving them an error when omitted).
Note that when the user clears the same field the OK button is disabled.
You can also add a hint to the EditText field(s) to indicate required (shown in second example).
Note that this was used as reference for the EditText listening (as I linked to in comment).
Finally, the last demo shows if you really wanted to show an error on field validation after the OK button is enabled and pressed. (From here.)
This should be obvious how to expand it to all your EditText fields. And bear in mind you can an condition to enabling the OK button - here it is just at least one character.
Button b = findViewById(R.id.main_button);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Log.e(TAG,"button");
View viewcustom = getLayoutInflater().inflate(R.layout.customdialog,null);
EditText edt1 = viewcustom.findViewById(R.id.description);
EditText edt2 = viewcustom.findViewById(R.id.age);
final AlertDialog.Builder alertDialog = new AlertDialog.Builder(MainActivity.this)
.setView(viewcustom)
.setPositiveButton("Ok", (dialogInterface, i) -> {
String d = edt1.getText().toString();
String a = edt2.getText().toString();
Toast.makeText(MainActivity.this,d, Toast.LENGTH_LONG).show();
});
alertDialog.setNegativeButton("Cancel", null);
AlertDialog ad = alertDialog.create();
edt1.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence sequence, int i, int i1, int i2) {}
#Override
public void onTextChanged(CharSequence sequence, int i, int i1, int i2) {}
#Override
public void afterTextChanged(Editable editable) {
if (edt1.getText().length() > 0) {
// if user enters anything then enable - modify criteria as desired
ad.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(true);
} else {
// if user deletes entry then back to disabled
ad.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(false);
}
}
});
// Initially OK button is disabled.
ad.show();
ad.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(false);
}
});
And demo:
You can also add a hint to each field to indicate it is required if nothing is entered as in :
<EditText
android:id="#+id/description"
android:hint="Field is required"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toTopOf="#id/age" />
Finally, if you really, really want to allow the OK but then do further validation to display errors then add the following. Note that the second field is treated as an Age field and the data entered must be an integer. A bit contrived but used to show an example.
// add this after the AlertDialog create()
ad.setOnShowListener(new DialogInterface.OnShowListener() {
#Override
public void onShow(DialogInterface anInterface) {
Button b = ad.getButton(DialogInterface.BUTTON_POSITIVE);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// do some validation on edit text
String s = edt2.getText().toString();
try {
Integer age = Integer.valueOf(s);
Toast.makeText(MainActivity.this,d+":"+age, Toast.LENGTH_LONG).show();
ad.dismiss();
} catch (Exception e) {
// complain
Toast.makeText(MainActivity.this, "Age must be an integer", Toast.LENGTH_LONG).show();
}
}
});
}
});
And demo of requiring the optional Age to be an integer:
I'm creating a form in android which asks for gender. To get this input I use Material Button Toggle Group which contains two buttons. I don't know how to know which button is clicked in my activity.java. How to get to know about the selected button in my activity so that i can save the details in different database.
myxml.xml
<com.google.android.material.button.MaterialButtonToggleGroup
android:id="#+id/toggleButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:singleSelection="true">
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Male"
android:layout_marginStart="5dp"
style="?attr/materialButtonOutlinedStyle"/>
<Button
android:id="#+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Female"
android:layout_marginStart="10dp"
style="?attr/materialButtonOutlinedStyle"/>
</com.google.android.material.button.MaterialButtonToggleGroup>
Myactivity.java
MaterialButtonToggleGroup toggleButton = findViewById(R.id.toggleButton);
toggleButton.addOnButtonCheckedListener();
// I CAN'T FIND ANY PROPER SOLUTION
You can use the getCheckedButtonId() method.
Something like:
MaterialButtonToggleGroup materialButtonToggleGroup =
findViewById(R.id.toggleButton);
int buttonId = materialButtonToggleGroup.getCheckedButtonId();
MaterialButton button = materialButtonToggleGroup.findViewById(buttonId);
Only if you need a listener you can use the addOnButtonCheckedListener:
materialButtonToggleGroup.addOnButtonCheckedListener(new MaterialButtonToggleGroup.OnButtonCheckedListener() {
#Override
public void onButtonChecked(MaterialButtonToggleGroup group, int checkedId, boolean isChecked) {
if (isChecked) {
if (checkedId == R.id.button1) {
//..
}
}
}
});
You have to check the checkedId value but also the isChecked value. The same listener is called when you check a button but also when you unckeck a button.
It means that if you click the button1 the listener is called with isChecked=true and checkedId=1. Then if you click the button2 the listener is called twice. Once with isChecked=false and checkedId=1, once with isChecked=true and checkedId=2.
You can do it like this :
toggleButton.addOnButtonCheckedListener(new MaterialButtonToggleGroup.OnButtonCheckedListener() {
#Override
public void onButtonChecked(MaterialButtonToggleGroup group, int checkedId, boolean isChecked) {
if(group.getCheckedButtonId()==R.id.button1)
{
//Place code related to button1 here
Toast.makeText(MainActivity2.this, "Button1 Clicked", Toast.LENGTH_SHORT).show();
}else if(group.getCheckedButtonId()==R.id.button2) {
//Place code related to button 2 here
Toast.makeText(MainActivity2.this, "Button2 Clicked", Toast.LENGTH_SHORT).show();
}
}
});
I would like to do something like a small selection form.
I would like to do a click event where if I select one of the first radiogroup and another one of the second it takes me to a new activity.
I got two radiogroups with two radiobuttons inside each.
<RadioGroup xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RadioButton android:id="#+id/physic"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="physic"
android:onClick="onRadioButtonClicked"/>
<RadioButton android:id="#+id/math"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="math"
android:onClick="onRadioButtonClicked"/>
</RadioGroup>
<RadioGroup xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RadioButton android:id="#+id/theories"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="theories"
android:onClick="onRadioButtonClicked"/>
<RadioButton android:id="#+id/problems_solving"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="problem solving"
android:onClick="onRadioButtonClicked"/>
</RadioGroup>
I declared my buttons and tried to use onRadioButtonClicked like below:
public void onRadioButtonClicked(View view) {
boolean checked = ((RadioButton) view).isChecked();
switch(view.getId()) {
case R.id.math:
if (checked)
switch(view.getId()) {
case R.id.problems_solving:
if (checked)
showFirstWord("math problem resolution");
break;
case R.id.theories:
if (checked)
showSecondWord("math theories");
break;
}
break;
case R.id.physic:
if (checked)
switch(view.getId()) {
case R.id.problems_solving:
if (checked)
showThirdWord("physic problem solving");
break;
case R.id.theories:
if (checked)
showFourthWord("physic theories");
break;
}
break;
}
}
I want the strings in the functions to appear in a text view in the other activities like below:
private void showFirstWord (String text) {
Intent first_word = new Intent(this, FirstActivity.class);
first_word.putExtra("key", text);
startActivity(first_word);
}
private void showSecondWord (String text) {
Intent second_word = new Intent(this, SecondActivity.class);
second_word.putExtra("key", text);
startActivity(second_word);
}
private void showThirdWord (String text) {
Intent third_word = new Intent(this, ThirdActivity.class);
third_word.putExtra("key", text);
startActivity(third_word);
}
private void showFourthWord (String text) {
Intent fourth_word = new Intent(this, FourthActivity.class);
fourth_word.putExtra("key", text);
startActivity(fourth_word);
}
I tried to follow this page from Android developers but I'm still not sure what to do with it: https://stuff.mit.edu/afs/sipb/project/android/docs/guide/topics/ui/controls/radiobutton.html
My method doesn't seem to be correct ass I can't get the strings to appear in the other activities. Is my reasonning ok for now or should I study another method?
Thanks :)
You can simplified your code onRadioButtonClicked just create first a String variable called subjectSelected.
then:
private String subjectSelected = "";
public void onRadioButtonClicked(View view) {
RadioButton radioButton = (RadioButton) view;
switch(view.getId()) {
case R.id.math:
subjectSelected = radioButton.getText().toString();
break;
case R.id.physic:
subjectSelected = radioButton.getText().toString();
break;
case R.id.problems_solving:
if (subjectSelected.equals("math")) {
showFirstWord ("math problem resolution");
} else if (subjectSelected.equals("physic")) {
showThirdWord("physic problem solving");
}
break;
case R.id.theories:
if (subjectSelected.equals("math")) {
showSecondWord("math theories");
} else if (subjectSelected.equals("physic")) {
showFourthWord("physic theories");
}
break;
}
}
and to display the text you pass to another activity. Use a Bundle to get the value of your key.
e.g.:
public class FirstActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_first);
Bundle bundle = getIntent().getExtras();
String key = bundle.getString("key");
TextView textView = (TextView) findViewById(R.id.textView1); // Replace the textView1 with the id you set to your textview.
textView.setText(key);
}
}
You can copy the codes of your FirstActivity and paste to your SecondActivity, ThirdActivity and FourthActivity to get the key.
String str; // store the text corresponding to the RadioButton which is clicked
switch(view.getId()) {
case R.id.radioButton1:
if (checked)
str = "button1Text";
break;
case R.id.radioButton2:
if (checked)
str = "button2Text";
break;
case R.id.radioButton3:
if (checked)
str = "button3Text";
break;
}
Intent intent = new Intent(this, WinderDTActivity.class);
intent.putExtra("radioChosen", str); // pass "str" to the next Activity
friends. I started to learn Android app developinng with Android Studio and Java. Now i am trying to make one progressbar. When app is started we have two EditText fields where first is 100 by default(how will be the max value for progressbar ) and one EditText field for increment by(this is step) for progressbar. When we click Start it must show up via dialog.
I write the code, there is no more errors, but app is closing when i hit the Start Button. The progressbar is not working
This is the code:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TextView
android:id="#+id/txt_max"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Max Value" />
<EditText
android:id="#+id/maximum"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="100.0" />
<TextView
android:id="#+id/txt_increment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Increment by"/>
<EditText
android:id="#+id/increment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="5.0" />
<Button
android:id="#+id/butt_Start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Start" />
</LinearLayout>
This is the MainActivity.java:
public class MainActivity extends AppCompatActivity {
int increment;
ProgressDialog dialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button startButton = (Button) findViewById(R.id.butt_Start);
startButton.setOnClickListener(new View.OnClickListener()
{
public void onClick(View view)
{
EditText et = (EditText) findViewById(increment);
increment = Integer.parseInt(et.getText().toString());
dialog = new ProgressDialog(MainActivity.this);
dialog.setCancelable(true);
dialog.setMessage("Loading...");
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
dialog.setProgress(0);
EditText max = (EditText) findViewById(R.id.maximum);
int maximum = Integer.parseInt(max.getText().toString());
dialog.setMax(maximum);
dialog.show();
Thread background = new Thread(new Runnable()
{
public void run()
{
try
{
while (dialog.getProgress() <= dialog.getMax())
{
Thread.sleep(500);
progressHandler.sendMessage(progressHandler.obtainMessage());
}
} catch (java.lang.InterruptedException e)
{
}
}
});
background.start();
}
Handler progressHandler = new Handler() {
public void handleMessage(Message msg) {
dialog.incrementProgressBy(increment);
}
};
});
}
}
There are some error with that code.. I will comment each by reporting your snippet:
public class MainActivity extends AppCompatActivity {
int increment;
ProgressDialog dialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button startButton = (Button) findViewById(R.id.butt_Start);
startButton.setOnClickListener(new View.OnClickListener()
{
public void onClick(View view)
{
EditText et = (EditText) findViewById(increment);
Here is the first error: not really a wrong thing, but it's better to istantiate the EditText in your onCreate (outside the onClick), because this way you will re-create the EditText every time you click the button.
The error is double: you are using findViewById(increment) where, in your code, increment is an int variable whose value is actually 0. You have to use (as you did for the button)
findViewById(R.id.increment);
Going on:
increment = Integer.parseInt(et.getText().toString());
dialog = new ProgressDialog(MainActivity.this);
dialog.setCancelable(true);
dialog.setMessage("Loading...");
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
dialog.setProgress(0);
EditText max = (EditText) findViewById(R.id.maximum);
int maximum = Integer.parseInt(max.getText().toString());
Here the error is xml side: since you are assuming that max.getText().toString() is an Integer, add inputType to your xml with number value.
dialog.setMax(maximum);
dialog.show();
Thread background = new Thread(new Runnable()
{
public void run()
{
try
{
while (dialog.getProgress() <= dialog.getMax())
{
Thread.sleep(500);
progressHandler.sendMessage(progressHandler.obtainMessage());
}
} catch (java.lang.InterruptedException e)
{
}
}
});
background.start();
}
Handler progressHandler = new Handler() {
public void handleMessage(Message msg) {
dialog.incrementProgressBy(increment);
}
};
});
}
}
Another thing is that is better to avoid naming a variable with same name of your id, expecially because id should be representative of the control you are pointing at (for example call it "EditTextMaxValueMainActivity", this is a limit example but it is representative).
If I can suggest you, TheNewBoston channel/site is the best for tutorials, it has a couple of playlist with android basics to advanced and it is simple and really explicative. Good luck!
for other errors, we will need the logtrace
The Answer for me is here:
This line:
EditText et = (EditText) findViewById(increment);
Must be changed to:
EditText et = (EditText) findViewById**(R.id.increment)**;
And i go to design view of activity_main.xml and changed the inputType of increment EditText and maximum EditText to number.
And removed the decimal format from the numbers.
<EditText
android:id="#+id/increment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="5" />
And here i had number with decimal, now i removed them.
<EditText
android:id="#+id/maximum"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="100" />
I have two RadioButton in a RadioGroup:
<RadioGroup
android:id="#+id/rgTripType"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="4" >
<RadioButton
android:id="#+id/rbOneWay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="One Way" />
<RadioButton
android:id="#+id/rbRound"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Round" />
</RadioGroup>
I am calling the RadioGroup in my Java file as:
final RadioGroup rgTypeOfTrip = (RadioGroup) findViewById(R.id.rgTripType);
btnCalc.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Toast.makeText(MainActivity.this, CALL FUNCTION GETINDEX() to get value, Toast.LENGTH_SHORT).show();
});
rgTypeOfTrip.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
// TODO Auto-generated method stub
// Method 1
int pos=rgTypeOfTrip.indexOfChild(findViewById(checkedId));
getIndex(pos);
Toast.makeText(MainActivity.this, String.valueOf(pos), Toast.LENGTH_SHORT).show();
}
});
public int getIndex(int k) {
return k;
}
What it is supposed to do is display a Toast with the index of the radio button within the radio group. Instead, it causes my program to crash. Any idea how to resolve it?
UPDATE: The index issue is solved.
Issue: How can I use the index value (POS) in the btnClick function?
It crashes because pos is an integer change. If you pass an int value as second paramter you are asking android to look for a String with id the int you provide. If it does not exists the ResourcesNotFoundException will be thrown
Toast.makeText(MainActivity.this, pos, Toast.LENGTH_SHORT).show();
with
Toast.makeText(MainActivity.this, String.valueOf(pos), Toast.LENGTH_SHORT).show();
There are different way ..
I used this way
RadioGroup radiogroup = (RadioGroup) findViewById(R.id.groupid);
Button bt = (Button) findViewById(R.id.btnDisplay);
bt.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// get selected radio button from radioGroup
int selectedId = radiogroup.getCheckedRadioButtonId();
switch (selectedId) {
case R.id.radio_button1:
// do something..
break;
case R.id.radio_button2:
// do something..
break;
}
}
});