Android RadioGroup checkedId out of bound - android

I am doing an app in which I must generate checkboxes with certain base values for the initial selected item and then change it's value. Nothing very complicated there.
My problem is when i reset the layout, I create a new RadioGroup with new RadioButtons and a new OnCheckedChangeListener for the RadioGroup. But when I click on a checkbox after resetting the UI, the checkId coming from the listener outputs something too big out of the bound of my RadioGroup.
Here's my code. I won't show the reset part but mainly I call removeAllViews() and then generate the layout again.
final RadioGroup optGroup = new RadioGroup(getActivity());
optGroup.setOrientation(LinearLayout.HORIZONTAL);
for(int itemNo = 0; itemNo < cell.getList().countItems(); itemNo++){
RadioButton rButton = new RadioButton(getActivity());
rButton.setText(cell.getList().getItem(itemNo).getLabel());
optGroup.addView(rButton);
if(cell.getSelectedListItem().getLabel().equals(cell.getList().getItem(itemNo).getLabel())){
optGroup.check(itemNo+1);
}
}
optGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
cell.selectListItem(String.valueOf(checkedId));
}
});
linearLayout.addView(optGroup);
When I log my input, before resetting the UI, the output ranges from 1 to 3 (I have 3 checkboxes) and after the reset, it ranges from 4 to 6.
EDIT The initial check only works for the first time too, like if the range of the 3 displayed was from 4 to 6 the second time.
Thanks!

You should set the radioButton ID
rButton.setId(itemNo);
But make sure not to use 0 as Id.
Since each RadioButton Id must be unique, I guess OS is keeping track of what autogenerated Ids were used (1-3) for the first run. Then after reset, it goes with 4-6, (resumed count from 3)

Related

Android RadioButton Confirm Selection

In my Android Application it's required to give a notification(warning) message before user change Radio Group Selection.
Basically I am trying to give a dialog message (that have warning message and YES/NO buttons to confirm change) when user click any other radio button within that Radio groiup.
If user presses YES then to change readio button selection with what user wanted to change, otherwise (if press NO) to select back with what was selected before.
I don't see any option in onCheckedChanged method when listen to OnCheckedChangeListener. What would be the best way to do this. Thanks
EDITS
I'm providing the warning message from a Dialog within onCheckedChanged method with option to Confirm the change (with YES/NO buttons). Problem is when user don't want the new selection after seeing the warning, I need a way to know the prevoiusly selected Radio Button to revert user's new selection.
public void onCheckedChanged(RadioGroup group, int checkedId)
The above method provides "checkedId" but how to know which Radio Button had selected before. It's required when user want to Cancel change..
Can do this by tracking the ealier selection defining a class level variable to hold old Radio button ID or some other logic like that. But there should be a straight forward way in Radio group to cancel new selection (by selecting old one back). I looked for beforeRadioCheckChange Type listener but didn't manage to find
You can store selected button before (when you actually set which one of radio buttons should be checked initially):
int selectedButton = mRadioGroup.getCheckedRadioButtonId();
And update it inside onCheckedChanged callback:
selectedButton = group.getCheckedRadioButtonId();
when user confirms change. Otherwise return checked state to the last selectedButton.
there is no a method in RadioGroup that enables you to revert your action, however you can easily achieve this by holding the id of selected RadioButton in an outside variable, and use it to revert your changes back:
RadioGroup radio;
static int buttonChecked;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
radio = (RadioGroup) findViewById(R.id.radioGroup);
buttonChecked = radio.getCheckedRadioButtonId(); // be sure to get the checked button id first time before assigning the onCheckedChange
radio.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
// Raise Dialog
if(yes){ // User confirmeed
buttonChecked = checkedId;
}else{ // User refused
if(buttonChecked != -1) // to prevent app from crashing if nothing is already selected
radio.check(buttonChecked);
else
radio.clearCheck();
}
}
});
}

RadioGroup onCheckChanged(RadioGroup radioGroup, int checkedId) not working correctly with dynamic forms

Dynamic forms on Android can be very confusing, and I have run into this specific situation where I am creating a list of options via a RadioGroup with AppCompatRadioButtons where the checkedId is not contextual with the Dynamic RadioGroup:
String [] options = new String[] {"Option 1", "Option 2", "Option 3", "Option 4"};
private void buildDynamicRadioGroup(){
final LinearLayout linearLayout = new LinearLayout(MyActivity.class);
final RadioGroup radioGroup = new RadioGroup(MyActivity.class);
for(String option: options){
final AppCompatRadioButton radioButton = new AppCompatRadioButton(MyActivity.class);
radioButton.setText(option);
radioGroup.addView(radioButton);
}
radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
Log.d("Checked Group Count", group.getChildCount()); // this is always 4
Log.d("Option Id", checkedId); // this prints correctly the first time
}
});
linearLayout.addView(radioGroup);
}
This looks okay for the first call to buildDynamicRadioGroup(), however every addition call to the method (i.e. n > 1) the checkedId is reflective of the total count of AppCompatRadioButton that have been built by calling this method, not the actual checkedId of the RadioGroup in question...
For example: the second call to the method prints 4, and 6 if the 2 item is selected in the 2 group of RadioButtons since there are 6 AppCompatRadioButtons
Anyone know how to handle this so I only get the checkedId in context with the RadioGroup ?
Just today I had the same problem and found your question when searching for a solution. The only difference is that I am loading the RadioButtons from XML resources.
For me the problem was, that all radio buttons had the same ID. The RadioGroup is working with these IDs when toggling the states for the radio buttons.
I could solve my problem by changing the ID of the radio buttons before adding them to the RadioGroup. Therefore I am just adding a random positive ID:
private View createViewForButton(
final Context context,
final Option radioButton) {
final View view =
getLayoutInflater(context).inflate(R.layout.form_radiobutton, null);
final RadioButton label = (RadioButton) view.findViewById(R.id.label_view);
label.setText(radioButton.getValue());
makeButtonWorkingInRadioGroup(view);
return view;
}
private void makeButtonWorkingInRadioGroup(final View view) {
// The radio group requires all RadioButtons to have different IDs to
// work correctly. This wouldn't work else as we are loading all
// RadioButtons from the same XML file having the same ID definition.
view.setId(View.generateViewId());
}
Make sure that the IDs you set are positive. With negative IDs its also not working.

disable button click for certain rows of buttons

I dynamically create Buttons by entering a word. If I write "met", it appears on the screen - one Button per letter. The same thing happens for the next word I enter, and it appears below the previous word --- as shown in the image above.
When I click on a Button it turns green. My question is, what is the best way to disable the clicking of a row of Buttons. Meaning, if the user clicks on the 'm' in "met" I want the user to only be able to click on the Buttons in "met" and to not be able to click on any of the Buttons in "had", "goes", or "ran"
Here is my code:
EDIT
int size = enter_txt.getText().toString().length();
for (int i=0; i<size; i++){
final Button dynamicButtons = new Button(view.getContext());
dynamicButtons.setLayoutParams(rlp);
dynamicButtons.getLayoutParams().width = 130;
dynamicButtons.getLayoutParams().height = 130;
dynamicButtons.setTag("0");
dynamicButtons.setId(1);
dynamicButtons.setText(edit_text_array[i]);
dynamicButtons.setBackgroundResource(R.drawable.button);
button_list.add(dynamicButtons);
linearLayout2.addView(dynamicButtons, rlp);
dynamicButtons.setOnClickListener(
new View.OnClickListener()
{
public void onClick(View view)
{
int i=0;
LinearLayout ll = (LinearLayout) dynamicButtons.getParent();
for(i=0; i<list_of_ll.size();i++){
if (ll == list_of_ll.get(i)){
list_of_ll.get(i).setId(i);
break;
}
}
if(list_of_ll.get(i).getId()==i)
ButtonOnClick(view);
}
});
}
linearLayout2.setId(0);
linearLayout2.setTag("0");
list_of_ll.add(linearLayout2);
EDIT
I created a List of the LinearLayouts for each row of Buttons. The Buttons turn green if the id of the LinearLayout is set to 1. When I click on a Button I want that LinearLayout to stay at 1 and have all other rows/LinearLayouts set to 0 so they become unclickable.
Currently, every Button I click turns green even if it's in a different row. Can someone please help me solve this issue?
Why you don't set Id in the for loop so that you are able to refer and set the onlicklistener to null like jpcrow already mentioned.
Set Id like:
YourCreatedBtn.setId(i+1);
//Id's setted programmatically don't.
have to be unique... But they should be
a positive number (referring to the
android documentation)
And in your on click method simply set onclicklistener for specified Id's to null. Just a hint, hope it helps
Update regarding Thread-openers Comment
I found two simple ways but i would prefer the one which is not commented out in the buttonIsClicked:
LinearLayout llrow;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
llrow = (LinearLayout) findViewById(R.id.test_layout);
//Adding 5 Buttons
for(int i = 0; i<5; i++) {
Button mybtn = new Button(this);
//set LayoutParams here
mybtn.setId(5);
mybtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
buttonIsClicked(v);
}
});
llrow.addView(mybtn);
}
}
private void buttonIsClicked(View v) {
/*ArrayList<View> myButtons = llrow.getTouchables();
for(int i = 0; i < llrow.getChildCount(); i++){
myButtons.get(i).setOnClickListener(null);
}*/
for(int i = 0; i<llrow.getChildCount(); i++){
llrow.getChildAt(i).setOnClickListener(null);
}
}
It's just a simplified Version of your code, but i'm sure you will get the Content..
What if found out is, that you don't have to set the ID in both cases.. You can easily get all the child over
YourRowLinearLayout.getChildAt(starting from 0 to n-1-Views you added)...
I didn't found a way around the for-loop... But this small-little loop will not break your neck regarding to Performance..
The outcommented-code is the second Approach, finding all the Child over getTouchables which logically leads to an ArrayList and that's exactly the reason why i don't like it. You have to initialize an arraylist...... However, this also won't break your neck regarding to Performance but a penny saved is a penny got! ;) Hope it helps and everything is clear. Both of them work! Please mark as accepted answere if it fits your Needs...
You have to distinguish between the two rows, either add them to different ViewGroups or you can use View.setTag(int key, Object tag)

Two radio buttons getting selected in Radio Group

Two buttons getting selected in the radio group.
I do not know where I am getting wrong. Please help me out.
final RadioGroup rg=new RadioGroup(Survay_MainActivity.this);
rg.clearCheck();
rg.setId(Integer.valueOf(entry1.getKey()));
Log.v("rg getid", "rg"+rg.getId());
for(int i =0;i<values.size();i++){
// Create Button
final RadioButton btn = new RadioButton(Survay_MainActivity.this);
btn.setId(i);
btn.setTextColor(Color.parseColor("#000000"));
btn.setBackgroundColor(Color.TRANSPARENT);
btn.setGravity(Gravity.LEFT);
btn.setText(values.get(i));
rg.addView(btn);
btn.setLayoutParams(params);
btn.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
JSONObject quesAns = new JSONObject();
String ans=btn.getText().toString().trim();
try {
quesAns.put(String.valueOf(rg.getId()), ans);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
jsonarray.put(quesAns);
Log.v("jsonarray", "jsonarray"+jsonarray);
}
});
}
views.addView(rg);
1) I am creating the RadioGroup out of the loop.
2) Adding radio button to the RadioGroup in the for loop
3) When the loop finishes the RadioGroup is added to the linerlayout.
You just need to change different ids for different radio button.
There may be some id clash in gen file.
Radio button1 : android:id="#+id/one
Radio button2 : android:id="#+id/two"
Radio button3 : android:id="#+id/three"
Hope this would help.
There are some things misplaced these changes you have to make out.
1.Change your OnClickListener by OnCheckChangeListener
2.Clear check your radioGroup after adding all radioButtons and before adding it in LinearLayout.
Your problem comes from the fact that you are setting an id for your items manually
rg.setId(Integer.valueOf(entry1.getKey()));
btn.setId(i);
Android works with id's generated automatically that are different. Setting the id's manually it might happen that you give the same ID to the radio group and the radio button.
I used your code and set the group to ID 3 and radios from 0 to 4.
Needless to say that after I click the button with id 3 it always stays on because the group has the same id.
So, try to remove the id setting part, or, if you insist make sure you always have distinct id's.
I faced the same problem. The cause is the RadioGroup's id is same as one of RadioButtons
the problem is this line. you didn't send where is this code belonged to. when you get out of this scope and come back you will create new RadioGroup. You should have one and only one RadioGroup so the RadioButtons have same RadioGroup and by default one of them will be selected. To this, you can define RadioGroup in an XML and use this to define variable for it RadioGroup rg = (RadioGroup) findViewById(R.id.YOURNAME); or you can define your RadioGroup as Instance variable(Global).
final RadioGroup rg=new RadioGroup(Survay_MainActivity.this);

android: radio buttons inside radio buttons

I am quite new to Android and this is my first application, so please correct if my question is not clear and I will gladly add more information about what I am trying to achieve.
I have a radio group built dynamically. Inside this radio group I would like to have another radio group, depending on the radio button chosen from the first group.
So, let's say I have an array list of items and for each item I have some sizes available (i.e: XS, S, L). If I check the radio button "XS", I would like to have another radio group with the available colors for the selected size, XS.
The way I have built this is by creating a radio group and it's radio buttons dynamically. Inside the method onCheckedChanged(), I am calling the method createRadioButtonsForAvailableColors(). This one creates the radio buttons with the necessary colors for the checked size, but once I check another size in the upper radio group, the new colors available for this size are added to the colors shown for the size selected before.
Thank you.
Here is my on create method:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_show_product_details);
sizesList = getSizes(getIDFromPreviousActivity());
createRadioButtonsForAvailableSizes(sizesList);
}
Here is my creation for the radio group containing the radio buttons with the available sizes:
// creates the radio buttons with the available sizes
public void createRadioButtonsForAvailableSizes(ArrayList<String> sizeList) {
productDetailsLayout = (LinearLayout) findViewById(R.id.productDetailsLayout);
RadioGroup rg = new RadioGroup(this);
rg.setOrientation(RadioGroup.HORIZONTAL);
int n = sizeList.size();
final RadioButton[] rb = new RadioButton[n];
for(int i=0; i< sizeList.size(); i++) {
colorList = getColors(getIDFromPreviousActivity(),sizeList.get(i));
rg.setOrientation(RadioGroup.HORIZONTAL);
rb[i] = new RadioButton(this);
rg.addView(rb[i]);
rb[i].setText(sizesList.get(i).toString());
rb[i].setId(getIDForRadioButton(sizesList.get(i).toString()));
rb[i].setButtonDrawable(R.drawable.radiobuttonunchecked);
rb[i].setOnCheckedChangeListener(this);
}
productDetailsLayout.addView(rg);
productDetailsLayout.setPadding(50, 50, 50, 50);
}
Here is the creation of the colors (same as for the sizes):
// create radio buttons for available colors
public void createRadioButtonsForAvailableColors(ArrayList<String> colorList) {
Log.d("createRadioButtonsForAvailableColors","");
productDetailsLayout = (LinearLayout) findViewById(R.id.productDetailsLayout);
RadioGroup rg = new RadioGroup(this);
rg.setOrientation(RadioGroup.HORIZONTAL);
int n = colorList.size();
final RadioButton[] rb = new RadioButton[n];
for(int i=0; i< colorList.size(); i++) {
Log.d("color"+i,colorList.get(i));
rg.setOrientation(RadioGroup.HORIZONTAL);
rb[i] = new RadioButton(this);
rg.addView(rb[i]);
rb[i].setText(colorList.get(i).toString());
rb[i].setId(getIDForRadioButton(colorList.get(i).toString()));
rb[i].setButtonDrawable(R.drawable.radiobuttonunchecked);
rb[i].setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override public void onCheckedChanged(CompoundButton button, boolean isChecked) {
button.setButtonDrawable(isChecked ? R.drawable.radiobuttonchecked : R.drawable.radiobuttonunchecked);
}
});
}
productDetailsLayout.addView(rg);
productDetailsLayout.setPadding(50, 50, 50, 50);
}
Here is my onCheckedChange method:
#Override
public void onCheckedChanged(CompoundButton button, boolean isChecked) {
button.setButtonDrawable(isChecked ? R.drawable.radiobuttonchecked : R.drawable.radiobuttonunchecked);
String text = button.getText().toString();
int productID = getIDFromPreviousActivity();
ArrayList<String> colorList = getColors(productID, text);
createRadioButtonsForAvailableColors(colorList);
}
The inner group is created right, but upon checking one size in the first group, it builds the subgroup radio buttons normally. If I click one size, it shows the available colors. But, on changing the size checked, the buttons showing the colors of the now selected size are added to the buttons shown before for the previous size selected. How can I cancel the inner buttons created when I selected first time the size and show only the available colors for the currently selected size?
I think this is maybe not the right approach to build it. So, I have 2 questions:
Usually, what would be the best way to do this? Since my inner radio group depends on the radio button chosen from the first group, I assume the creation of the inner group should be called inside the onCheckedChange() method. Should I start another activity from here or can I do it all in one activity?
If my approach is correct, can you please tell me how to delete the inner radio buttons created, in case the radio button from the main group is changed?
Thank you
So, if I understood this, the problem comes when you change the value of the sizes radio button, meaning the colors don't disappear.
Well, Java is all about a lot of boilerplating, and there's not pretty much to say (I'd probably go for a similar way).
You could add this inside the createRadioButtonsForAvailableColors method, just before you start adding content:
productDetailsLayout.removeViews(0, productDetailsLayout.getChildCount());
RemoveViews will remove any amount of child views starting from a position (hence I amb passing it 0 and the total of children).

Categories

Resources