1

I dynamically generate radiobuttons for an app (ex: 3 radiobuttons) in a LinearLayout I call parentLinearLayout. Problem is, they don't go automatically in a group, so if I check a button and then another, both check instead of un-checking the first one. So, I thought I should do a RadioGroup.

The app itself is a questionnaire app, and every question has a different number of possible answers. I create from a radiobutton layout the number of answers as radiobuttons.

Problem is, I get an error saying that I should remove the old view before doing so, but if I do this I lose my generated linearlayout: The specified child already has a parent. You must call removeView() on the child's parent first.

Here is my code:

public void drawRAnswers(int pst){
    int drawables = qmclist.get(pst).getAnswers().size();
    RadioGroup l1 = new RadioGroup(this);
    for (int i=0;i<drawables;i++){
        LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        final View rowView = inflater.inflate(R.layout.radiobutton, null);
        // Add the new row before the add field button.
        parentLinearLayout.addView(rowView, parentLinearLayout.getChildCount());
        rowView.setId(i);
        RadioButton rd = (RadioButton) rowView.findViewById(R.id.radiobtn);
        l1.addView(rd); <== HERE IS THE PROBLEM
        rd.setText(current.getAnswers().get(i).getAns());
    }
}

Any ideas how I could fix this? Thanks

Jonas
  • 121,568
  • 97
  • 310
  • 388
Vanhaeren Thomas
  • 367
  • 4
  • 15

3 Answers3

2
  1. You are creating a new layout during every iteration in loop.
  2. By inflating a new view, you are losing the old views
  3. Every time you are using the same id R.id.radiobtn for to find a view and add the same view again in the layout which is not possible hence the issue.

for (int i=0;i<drawables;i++){
        // 1,2
        LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
       // 
       final View rowView = inflater.inflate(R.layout.radiobutton, null);

        parentLinearLayout.addView(rowView, parentLinearLayout.getChildCount());
        rowView.setId(i);
        RadioButton rd = (RadioButton) rowView.findViewById(R.id.radiobtn);
        l1.addView(rd); // same view with same id R.id.radiobtn
        rd.setText(current.getAnswers().get(i).getAns());
    }

Solution :

public void drawRAnswers(int pst){
    int drawables = qmclist.get(pst).getAnswers().size();
    // create a radio group as container with direction
    RadioGroup l1 = new RadioGroup(this);
    l1.setOrientation(LinearLayout.VERTICAL);
    for (int i=0;i<drawables;i++){
        // create radio button, with id and text
        RadioButton rd = new RadioButton(this);
        rd.setId(i);
        rd.setText(current.getAnswers().get(i).getAns());
        // add radio button into group
        l1.addView(rd);
    }
    // finally, add radio group with buttons into parent layout  
    parentLinearLayout.addView(l1, parentLinearLayout.getChildCount());
}
Pavneet_Singh
  • 36,884
  • 5
  • 53
  • 68
  • Yes, the point is that I have a blank screen, and a layout containg only a radiobutton. For each iteration, I should add a radiobutton to the blank screen, and this is what I do. Thing is, they don't act like radiobuttons since I can select more than one, and this is what I want to fix. – Vanhaeren Thomas May 01 '18 at 18:26
  • To be more precise, my app is a questionnaire app, so depending on how many answers are to a question, I add the amount of radiobuttons respectively. – Vanhaeren Thomas May 01 '18 at 18:27
  • Yep, seems to be working, thanks, but now the radiobuttons are no longer aligned in rows. (they should be one below the other). – Vanhaeren Thomas May 01 '18 at 18:36
  • then use vertical orientation instead of horizontal – Pavneet_Singh May 01 '18 at 18:37
  • Would you happen to know by chance how I could check once everything is drawn which radiobutton has been selected? When I click a button, see which one was selected? – Vanhaeren Thomas May 01 '18 at 18:39
  • you need to use [setOnCheckedChangeListener](https://stackoverflow.com/a/6781061/4936904)` on radio group – Pavneet_Singh May 01 '18 at 18:41
1

You are quite close I guess just change some of the lines and you are good to go.

public void drawRAnswers(int pst){
    LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    int drawables = qmclist.get(pst).getAnswers().size();
    RadioGroup l1 = new RadioGroup(this);
    for (int i=0;i<drawables;i++){
        final View rowView = inflater.inflate(R.layout.radiobutton, null);
        // Add the new row before the add field button.
        RadioButton rd = (RadioButton) rowView.findViewById(R.id.radiobtn);
        rd.setText(current.getAnswers().get(i).getAns());
        rd.setId(i);
        l1.addView(rd);
    }

 parentLinearLayout.addView(l1, parentLinearLayout.getChildCount());
 //or
 parentLinearLayout.addView(l1);
}
vikas kumar
  • 10,447
  • 2
  • 46
  • 52
1

RadioGroups are glorified LinearLayouts behind the scenes, that means they can support any children, but will only treat RadioButtons in the same “group” if they are direct children of the Group. E.g.:

Imagine This hierarchy:

<RadioGroup> // THIS YOU HAVE IN XML
   <RadioButton 1> // ALL THESE YOU CREATE PROGRAMMATICALLY
   <RadioButton 2>
   <RadioButton 3>
</RadioGroup>

So your XML looks like:

<RadioGroup xmlns:android="http://schemas.android.com/apk/res/android"
            android:id="@+id/your_radio_button"
            android:layout_width=“match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">
            <!-- Radio Buttons will be programmatically added here -->
</RadioGroup>

So… you create everything programmatically, that’s fine. You have a “loop” like…

final RadioGroup group = //find your_radio_button in the layout.

// now iterate
for (Something something : listOfSomethings) {
     final RadioButton rb = new RadioButton(context);
     rb.setId(View.generateViewId());
     rb.setText(something.giveMeTheText());
     rb.setLayoutParams(layoutParams); // make these depending what your container for the RadioGroup is.
     rb.setOnCheckedChangeListener(your OnCheckedChangeListener);
     group.add(rb);
}

If you need to listen for changes, obviously add a common CompoundButton.OnCheckedChangeListener and override:

 @Override
 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
    // do what you need ;) 
 }

Bear in mind that the moment you do group.add(rb) if the Button has an onCheckedChangeListener, it will be fired… if you set it as checked (I think it also fires even if you don’t with a “false”), so you may want to delay the assignment of the listener until you’re done adding buttons to the RadioGroup and then iterate them and add them all at the same time (that doesn’t trigger the callback right there because the buttons are ALREADY in the hierarchy and haven’t changed).

If you need to insert something other than a RadioButton as the direct child of your RadioGroup that’s the topic for another question (it’s doable, not automatic and will require you to do some extra-work).

Martin Marconcini
  • 26,875
  • 19
  • 106
  • 144