1

I have a group of radiobuttons in a radiogroup that refuses to behave the way I'd like. The radiobuttons need to be two lines of two, and one line of one, with the last button having an edittext instead of a label. The layout looks correct, but the radiobuttons allow more than one to be selected and won't deselect any. Below is my XML:

    <RadioGroup
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/rgDesignation">

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/llVT1">

        <RadioButton
            android:text="@string/pressure_equipment"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/rbPE"
            android:layout_weight="1" />

        <RadioButton
            android:text="@string/assemblies"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/rbAss"
            android:layout_weight="1" />
    </LinearLayout>

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/llVT2">

        <RadioButton
            android:text="@string/unheated"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/rbUnh"
            android:layout_weight="1" />

        <RadioButton
            android:text="@string/heated"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/rbH"
            android:layout_weight="1" />

    </LinearLayout>

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:id="@+id/llVT3">

        <RadioButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/rbOwnSel"
            android:layout_weight="0" />

        <EditText
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:inputType="text"
            android:ems="10"
            android:id="@+id/etOwnChoice"
            android:layout_weight="1"
            android:textColor="@android:color/black"
            android:background="@android:color/white"
            android:elevation="5dp" />
    </LinearLayout>

    </RadioGroup>
b0b
  • 33
  • 2
  • 8

1 Answers1

0

Make custom RadioGroup class like this:

public class RadioGroup extends LinearLayout {

private int mCheckedId = -1;

private CompoundButton.OnCheckedChangeListener mChildOnCheckedChangeListener;

private boolean mProtectFromCheckedChange = false;
private OnCheckedChangeListener mOnCheckedChangeListener;
private PassThroughHierarchyChangeListener mPassThroughListener;


public RadioGroup(Context context) {
    super(context);
    setOrientation(VERTICAL);
    init();
}


public RadioGroup(Context context, AttributeSet attrs) {
    super(context, attrs);
    init();
}

private void init() {
    mChildOnCheckedChangeListener = new CheckedStateTracker();
    mPassThroughListener = new PassThroughHierarchyChangeListener();
    super.setOnHierarchyChangeListener(mPassThroughListener);
}


@Override
public void setOnHierarchyChangeListener(OnHierarchyChangeListener listener) {

    mPassThroughListener.mOnHierarchyChangeListener = listener;
}

@Override
protected void onFinishInflate() {
    super.onFinishInflate();


    if (mCheckedId != -1) {
        mProtectFromCheckedChange = true;
        setCheckedStateForView(mCheckedId, true);
        mProtectFromCheckedChange = false;
        setCheckedId(mCheckedId);
    }
}

@Override
public void addView(View child, int index, ViewGroup.LayoutParams params) {
    if (child instanceof RadioButton) {
        final RadioButton button = (RadioButton) child;
        if (button.isChecked()) {
            mProtectFromCheckedChange = true;
            if (mCheckedId != -1) {
                setCheckedStateForView(mCheckedId, false);
            }
            mProtectFromCheckedChange = false;
            setCheckedId(button.getId());
        }
    }

    super.addView(child, index, params);
}


public void check(@IdRes int id) {
    // don't even bother
    if (id != -1 && (id == mCheckedId)) {
        return;
    }

    if (mCheckedId != -1) {
        setCheckedStateForView(mCheckedId, false);
    }

    if (id != -1) {
        setCheckedStateForView(id, true);
    }

    setCheckedId(id);
}

private void setCheckedId(@IdRes int id) {
    mCheckedId = id;
    if (mOnCheckedChangeListener != null) {
        mOnCheckedChangeListener.onCheckedChanged(this, mCheckedId);
    }
}

private void setCheckedStateForView(int viewId, boolean checked) {
    View checkedView = findViewById(viewId);
    if (checkedView != null && checkedView instanceof RadioButton) {
        ((RadioButton) checkedView).setChecked(checked);
    }
}


@IdRes
public int getCheckedRadioButtonId() {
    return mCheckedId;
}


public void clearCheck() {
    check(-1);
}


public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {
    mOnCheckedChangeListener = listener;
}


@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
    return new LayoutParams(getContext(), attrs);
}

@Override
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
    return p instanceof RadioGroup.LayoutParams;
}

@Override
protected LinearLayout.LayoutParams generateDefaultLayoutParams() {
    return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
}

@Override
public CharSequence getAccessibilityClassName() {
    return RadioGroup.class.getName();
}


public static class LayoutParams extends LinearLayout.LayoutParams {

    public LayoutParams(Context c, AttributeSet attrs) {
        super(c, attrs);
    }


    public LayoutParams(int w, int h) {
        super(w, h);
    }


    public LayoutParams(int w, int h, float initWeight) {
        super(w, h, initWeight);
    }


    public LayoutParams(ViewGroup.LayoutParams p) {
        super(p);
    }


    public LayoutParams(MarginLayoutParams source) {
        super(source);
    }


    @Override
    protected void setBaseAttributes(TypedArray a,
                                     int widthAttr, int heightAttr) {

        if (a.hasValue(widthAttr)) {
            width = a.getLayoutDimension(widthAttr, "layout_width");
        } else {
            width = WRAP_CONTENT;
        }

        if (a.hasValue(heightAttr)) {
            height = a.getLayoutDimension(heightAttr, "layout_height");
        } else {
            height = WRAP_CONTENT;
        }
    }
}


    public void onCheckedChanged(RadioGroup group, @IdRes int checkedId);
}

private class CheckedStateTracker implements CompoundButton.OnCheckedChangeListener {
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        // prevents from infinite recursion
        if (mProtectFromCheckedChange) {
            return;
        }

        mProtectFromCheckedChange = true;
        if (mCheckedId != -1) {
            setCheckedStateForView(mCheckedId, false);
        }
        mProtectFromCheckedChange = false;

        int id = buttonView.getId();
        setCheckedId(id);
    }
}


private class PassThroughHierarchyChangeListener implements
        ViewGroup.OnHierarchyChangeListener {
    private ViewGroup.OnHierarchyChangeListener mOnHierarchyChangeListener;

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
    public void traverseTree(View view) {
        if (view instanceof RadioButton) {
            int id = view.getId();
            // generates an id if it's missing
            if (id == View.NO_ID) {
                id = View.generateViewId();
                view.setId(id);
            }
            ((RadioButton) view).setOnCheckedChangeListener(
                    mChildOnCheckedChangeListener);
        }
        if (!(view instanceof ViewGroup)) {
            return;
        }
        ViewGroup viewGroup = (ViewGroup) view;
        if (viewGroup.getChildCount() == 0) {
            return;
        }
        for (int i = 0; i < viewGroup.getChildCount(); i++) {
            traverseTree(viewGroup.getChildAt(i));
        }
    }

    /**
     * {@inheritDoc}
     */
    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
    public void onChildViewAdded(View parent, View child) {
        traverseTree(child);
        if (parent == RadioGroup.this && child instanceof RadioButton) {
            int id = child.getId();
            // generates an id if it's missing
            if (id == View.NO_ID) {
                id = View.generateViewId();
                child.setId(id);
            }
            ((RadioButton) child).setOnCheckedChangeListener(
                    mChildOnCheckedChangeListener);
        }

        if (mOnHierarchyChangeListener != null) {
            mOnHierarchyChangeListener.onChildViewAdded(parent, child);
        }
    }

    /**
     * {@inheritDoc}
     */
    public void onChildViewRemoved(View parent, View child) {
        if (parent == RadioGroup.this && child instanceof RadioButton) {
            ((RadioButton) child).setOnCheckedChangeListener(null);
        }

        if (mOnHierarchyChangeListener != null) {
            mOnHierarchyChangeListener.onChildViewRemoved(parent, child);
        }
    }
}

}

and add in your layout like this:

 <LinearLayout 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"
android:orientation="vertical"
android:padding="@dimen/activity_vertical_margin"
>

<com.example.admin.myapplication.RadioGroup
    android:id="@+id/radio_group_plus"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="60dp">

        <RadioButton
            android:id="@+id/rb_latte"
            android:text="radio1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_centerVertical="true" />

        <RadioButton
            android:text="radio2"
            android:id="@+id/rb_latte1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true" />
    </RelativeLayout>

    <View
        android:layout_width="match_parent"
        android:layout_height="2dp"
        android:background="#E0E0E0" />

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="60dp">

        <ImageView
            android:id="@+id/iv_mocha"
            android:layout_width="40dp"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:src="@mipmap/ic_launcher" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_toRightOf="@+id/iv_mocha"
            android:paddingLeft="20dp"
            android:text="Mocha" />

        <RadioButton
            android:id="@+id/rb_mocha"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true" />
    </RelativeLayout>

    <View
        android:layout_width="match_parent"
        android:layout_height="2dp"
        android:background="#E0E0E0" />

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="60dp">

        <ImageView
            android:id="@+id/iv_americano"
            android:layout_width="40dp"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:src="@mipmap/ic_launcher" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_toRightOf="@+id/iv_americano"
            android:paddingLeft="20dp"
            android:text="Americano" />

        <RadioButton
            android:id="@+id/rb_americano"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true" />
    </RelativeLayout>

    <View
        android:layout_width="match_parent"
        android:layout_height="2dp"
        android:background="#E0E0E0" />

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="60dp">

        <ImageView
            android:id="@+id/iv_espresso"
            android:layout_width="40dp"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:src="@mipmap/ic_launcher" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_toRightOf="@+id/iv_espresso"
            android:paddingLeft="20dp"
            android:text="Espresso" />

        <RadioButton
            android:id="@+id/rb_espresso"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true" />
    </RelativeLayout>

    <View
        android:layout_width="match_parent"
        android:layout_height="2dp"
        android:background="#E0E0E0" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:orientation="horizontal">

        <RelativeLayout
            android:layout_width="0dp"
            android:layout_height="60dp"
            android:layout_weight="1">

            <ImageView
                android:id="@+id/iv_orange"
                android:layout_width="40dp"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:src="@mipmap/ic_launcher" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_toRightOf="@+id/iv_orange"
                android:paddingLeft="20dp"
                android:text="Orange" />

            <RadioButton
                android:id="@+id/rb_orange"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:layout_centerVertical="true" />
        </RelativeLayout>

        <View
            android:layout_width="2dp"
            android:layout_height="wrap_content"
            android:layout_marginBottom="10dp"
            android:layout_marginTop="10dp"
            android:background="#E0E0E0" />

        <RelativeLayout
            android:layout_width="0dp"
            android:layout_height="60dp"
            android:layout_weight="1"
            android:paddingLeft="10dp">

            <ImageView
                android:id="@+id/iv_butter"
                android:layout_width="40dp"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:src="@mipmap/ic_launcher" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_toRightOf="@+id/iv_butter"
                android:paddingLeft="20dp"
                android:text="Butter" />

            <RadioButton
                android:id="@+id/rb_butter"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:layout_centerVertical="true" />
        </RelativeLayout>
    </LinearLayout>

</com.example.admin.myapplication.RadioGroup>

<Button
    android:layout_width="wrap_content"
    android:layout_height="48dp"
    android:layout_gravity="center"
    android:layout_marginTop="20dp"
    android:background="#138BE8"
    android:gravity="center"
    android:onClick="onOrderClicked"
    android:paddingLeft="20dp"
    android:paddingRight="20dp"
    android:text="Order Drink"
    android:textColor="@android:color/white" />

Vaibhavi
  • 61
  • 8
  • 1
    I did initially try to do something similar to this, but with mutliple embedded layouts it just failed to pick up the second radiobutton in an embedded layout. worked fine for the first button. I ended up going for http://stackoverflow.com/a/13273890/4185043 which is dirty and oldschool, but works perfectly. – b0b Mar 08 '17 at 10:11
  • i done one demo according to your requirement using this code, it works good. you try it once. – Vaibhavi Mar 08 '17 at 11:11
  • i edit layout code in above example. you can try it. – Vaibhavi Mar 08 '17 at 11:15
  • OnCheckedChangeListener which one import is used 1.RadioGroup, CompoundButton,ChipGroup – CrazyMind Jan 12 '21 at 07:18