RadioGroup with two columns which have ten RadioButtons

后端 未结 12 1872
难免孤独
难免孤独 2020-11-27 07:16

I have a RadioGroup and I want to align buttons next to each other in two columns and five rows and I am unable to achieve it. Things I have tried:

相关标签:
12条回答
  • 2020-11-27 07:42

    I created my own RadioGridLayout which include RadioGroup code and extends GridLayout. You can copy this code. For me working well. After you can use this layout in your xml. And customize like grid layout.

    For R.styleable.RadioGridLayout_checked I used code like this:

    <resources>
        <declare-styleable name="RadioGridLayout">
            <attr name="checked" format="integer" />
        </declare-styleable>
    </resources>
    
    public class RadioGridLayout extends GridLayout {
    
        private int mCheckedId = -1;
        private CompoundButton.OnCheckedChangeListener mChildOnCheckedChangeListener;
        private boolean mProtectFromCheckedChange = false;
        private OnCheckedChangeListener mOnCheckedChangeListener;
        private PassThroughHierarchyChangeListener mPassThroughListener;
    
        private void setCheckedId(@IdRes int id) {
            mCheckedId = id;
            if (mOnCheckedChangeListener != null) {
                mOnCheckedChangeListener.onCheckedChanged(this, mCheckedId);
            }
            AutofillManager afm = null;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                afm = getContext().getSystemService(AutofillManager.class);
            }
            if (afm != null) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    afm.notifyValueChanged(this);
                }
            }
        }
    
        public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {
            mOnCheckedChangeListener = listener;
        }
    
        public interface OnCheckedChangeListener {
            void onCheckedChanged(RadioGridLayout group, @IdRes int checkedId);
        }
    
        private int mInitialCheckedId = View.NO_ID;
    
        public RadioGridLayout(Context context) {
            super(context);
            setOrientation(VERTICAL);
            init();
        }
    
        public RadioGridLayout(Context context, AttributeSet attrs) {
            super(context, attrs);
    
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) {
                    setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_YES);
                }
            }
    
            TypedArray attributes = context.obtainStyledAttributes(
                    attrs,
                    R.styleable.RadioGridLayout,
                    R.attr.radioButtonStyle, 0);
    
            int value = attributes.getResourceId(R.styleable.RadioGridLayout_checked, View.NO_ID);
            if (value != View.NO_ID) {
                mCheckedId = value;
                mInitialCheckedId = value;
            }
    
            attributes.recycle();
            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) {
            if (id != -1 && (id == mCheckedId)) {
                return;
            }
    
            if (mCheckedId != -1) {
                setCheckedStateForView(mCheckedId, false);
            }
    
            if (id != -1) {
                setCheckedStateForView(id, true);
            }
    
            setCheckedId(id);
        }
    
        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);
        }
    
        @Override
        public GridLayout.LayoutParams generateLayoutParams(AttributeSet attrs) {
            return new GridLayout.LayoutParams(getContext(), attrs);
        }
    
        @Override
        protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
            return p instanceof RadioGroup.LayoutParams;
        }
    
        @Override
        protected GridLayout.LayoutParams generateDefaultLayoutParams() {
            return new LayoutParams();
        }
    
        @Override
        public CharSequence getAccessibilityClassName() {
            return RadioGroup.class.getName();
        }
    
        public static class LayoutParams extends GridLayout.LayoutParams {
    
            public LayoutParams(Spec rowSpec, Spec columnSpec) {
                super(rowSpec, columnSpec);
            }
    
            public LayoutParams() {
                super();
            }
    
            public LayoutParams(ViewGroup.LayoutParams params) {
                super(params);
            }
    
            public LayoutParams(MarginLayoutParams params) {
                super(params);
            }
    
            public LayoutParams(GridLayout.LayoutParams source) {
                super(source);
            }
    
            public LayoutParams(Context context, AttributeSet attrs) {
                super(context, attrs);
            }
    
            @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;
                }
            }
        }
    
        private class CheckedStateTracker implements CompoundButton.OnCheckedChangeListener {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                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;
    
            @Override
            public void onChildViewAdded(View parent, View child) {
                if (parent == RadioGridLayout.this && child instanceof RadioButton) {
                    int id = child.getId();
                    if (id == View.NO_ID) {
                        id = View.generateViewId();
                        child.setId(id);
                    }
                    ((RadioButton) child).setOnCheckedChangeListener(
                            mChildOnCheckedChangeListener);
                }
    
                if (mOnHierarchyChangeListener != null) {
                    mOnHierarchyChangeListener.onChildViewAdded(parent, child);
                }
            }
    
            @Override
            public void onChildViewRemoved(View parent, View child) {
                if (parent == RadioGridLayout.this && child instanceof RadioButton) {
                    ((RadioButton) child).setOnCheckedChangeListener(null);
                }
    
                if (mOnHierarchyChangeListener != null) {
                    mOnHierarchyChangeListener.onChildViewRemoved(parent, child);
                }
            }
        }
    
        @Override
        public void onProvideAutofillStructure(ViewStructure structure, int flags) {
            super.onProvideAutofillStructure(structure, flags);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                structure.setDataIsSensitive(mCheckedId != mInitialCheckedId);
            }
        }
    
        @Override
        public void autofill(AutofillValue value) {
            if (!isEnabled()) return;
    
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                if (!value.isList()) {
                    Timber.w(value + " could not be autofilled into " + this);
                    return;
                }
            }
    
            int index = 0;
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
                index = value.getListValue();
            }
            final View child = getChildAt(index);
            if (child == null) {
                Timber.w("RadioGroup.autoFill(): no child with index %s", index);
                return;
            }
    
            check(child.getId());
        }
    
        @Override
        public int getAutofillType() {
            return isEnabled() ? AUTOFILL_TYPE_LIST : AUTOFILL_TYPE_NONE;
        }
    
        @Override
        public AutofillValue getAutofillValue() {
            if (!isEnabled()) return null;
    
            final int count = getChildCount();
            for (int i = 0; i < count; i++) {
                final View child = getChildAt(i);
                if (child.getId() == mCheckedId) {
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                        return AutofillValue.forList(i);
                    }
                }
            }
            return null;
        }
    }
    
    0 讨论(0)
  • 2020-11-27 07:44

    This is what i did on my XML layout and it works fine.

      <RadioGroup
                    android:id="@+id/radioGroup"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="2dp">
    
                    <LinearLayout
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:orientation="horizontal">
    
                    <RadioButton
                        android:id="@+id/radioOwner"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_weight="1"
                        android:buttonTint="@color/login_button_color"
                        android:fontFamily="@font/rnhousesans_regular"
                        android:text="Owner"
                        android:textColor="@color/colorPrimary" />
    
                    <RadioButton
                        android:id="@+id/radioLivingParents"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_weight="1"
                        android:buttonTint="@color/login_button_color"
                        android:fontFamily="@font/rnhousesans_regular"
                        android:text="Living with parents"
                        android:textColor="@color/colorPrimary" />
    
                    </LinearLayout>
    
                    <LinearLayout
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:orientation="horizontal">
    
                    <RadioButton
                        android:id="@+id/radioTenant"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_weight="1"
                        android:buttonTint="@color/login_button_color"
                        android:fontFamily="@font/rnhousesans_regular"
                        android:text="Tenant"
                        android:textColor="@color/colorPrimary" />
    
                    <RadioButton
                        android:id="@+id/radioOther"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_weight="1"
                        android:buttonTint="@color/login_button_color"
                        android:fontFamily="@font/rnhousesans_regular"
                        android:text="Other"
                        android:textColor="@color/colorPrimary" />
    
                    </LinearLayout>
                </RadioGroup>
    
    0 讨论(0)
  • 2020-11-27 07:48

    Make 2 RadioGroup in the xml file using LinearLayout each having 5 RadioButton and using layout_weight property place them side by side on the screen. Then create listener for these radio groups as shown below:

    rg1 = (RadioGroup) findViewById(R.id.radiogroup1);
    rg2 = (RadioGroup) findViewById(R.id.radiogroup2);
    rg1.clearCheck();//this is so we can start fresh, with no selection on both RadioGroups
    rg2.clearCheck();
    rg1.setOnCheckedChangeListener(new OnCheckedChangeListener() {
    
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                // TODO Auto-generated method stub
                if (checkedId != -1) {
                    fun2();
                }
            }
        });
    
        rg2.setOnCheckedChangeListener(new OnCheckedChangeListener() {
    
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                // TODO Auto-generated method stub
                if (checkedId != -1) {
                    fun1();
                }
            }
        });
    

    And fun1() & fun2() will be defined as shown below:

    public void fun1() {
         rg1.setOnCheckedChangeListener(null);
         rg1.clearCheck();
         rg1.setOnCheckedChangeListener(new OnCheckedChangeListener() {
    
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                fun2();
                Log.v("Inside fun1","fun2");
            }
        });
    }
    
    public void fun2() {
         rg2.setOnCheckedChangeListener(null);
         rg2.clearCheck();
         rg2.setOnCheckedChangeListener(new OnCheckedChangeListener() {
    
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                // TODO Auto-generated method stub
                fun1();
                Log.v("Inside fun2","fun1");
    
            }
        });
    }
    
    0 讨论(0)
  • 2020-11-27 07:55

    You can use a nested GridLayout inside your RadioGroup, although you will loose the main property of the RadioGroup to manage RadioButtons: e.g. single item selection. RadioButtons should be direct children.

    <RadioGroup
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        >
    
        <GridLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:columnCount="2"
            >
    
        <androidx.appcompat.widget.AppCompatRadioButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Text 1"
            />
    
        <androidx.appcompat.widget.AppCompatRadioButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Text 2"
            />
    
        <androidx.appcompat.widget.AppCompatRadioButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Text 3"
            />
    
        <androidx.appcompat.widget.AppCompatRadioButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Text 4"
            />
    
        <androidx.appcompat.widget.AppCompatRadioButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Text 5"
            />
    
        </GridLayout>
    </RadioGroup>
    
    0 讨论(0)
  • 2020-11-27 07:56

    I had to do the same thing and wound up combining a TableLayout and a RadioButtonGroup. I added the radio buttons dynamically to TableRows. Here is the class:

    public class RadioGroupColumns extends TableLayout implements OnClickListener {
    
    private static final String TAG = "RadioGroupColumns";
    private RadioButton activeRadioButton;
    private int mCheckedId = -1;
    // tracks children radio buttons checked state
    private CompoundButton.OnCheckedChangeListener mChildOnCheckedChangeListener;
    // when true, mOnCheckedChangeListener discards events
    private boolean mProtectFromCheckedChange = false;
    private OnCheckedChangeListener mOnCheckedChangeListener;
    private PassThroughHierarchyChangeListener mPassThroughListener;
    
    public RadioGroupColumns(Context context) {
        super(context);
        setOrientation(VERTICAL);
        init();
    }
    
    public RadioGroupColumns(Context context, AttributeSet attrs) {
                super(context, attrs);
                Resources res = Resources.getSystem();
                int value = 0;
                // retrieve selected radio button as requested by the user in the
                // XML layout file
    
                TypedArray attributes = null;
                try {
                    attributes = context.obtainStyledAttributes(attrs, getAttributes(context), R.attr.radioButtonStyle, 0);
                    value = attributes.getResourceId(getAttribute(context), View.NO_ID);
                } catch (IllegalAccessException e) {
                    // TODO Auto-generated catch block
                    Log.d("Exception RadioGroupColumns Construct",e.toString());
                    e.printStackTrace();
                }
                catch (ClassNotFoundException e) { 
                    Log.d("Exception RadioGroupColumns Construct",e.toString());
                    e.printStackTrace();
                }  
    
    
                if (value != View.NO_ID) {
                    mCheckedId = value;
                }
    
                //hardcode it to vertical
                //final int index = attributes.getInt(com.android.internal.R.styleable.RadioGroup_orientation, VERTICAL);
                //setOrientation(index);
    
                attributes.recycle();
    
                setOrientation(VERTICAL);
                init();
    }
    
    @Override
    public void onClick(View v) {
        if (v instanceof TableRow) {
            TableRow row = (TableRow)v;
            for (int j=0;j<row.getChildCount();j++) { 
                if (RadioButton.class.isAssignableFrom(row.getChildAt(j).getClass())) {
    
                    ((RadioButton) row.getChildAt(j)).setChecked(true);
                    activeRadioButton = (RadioButton) row.getChildAt(j);
                }
            }
        }
        else { 
            final RadioButton rb = (RadioButton) v;
    
            if (activeRadioButton != null) {
                activeRadioButton.setChecked(false);
            }
            rb.setChecked(true);
            activeRadioButton = rb;
        }
    
    }
    
    private void init() {
        mChildOnCheckedChangeListener = new CheckedStateTracker();
        mPassThroughListener = new PassThroughHierarchyChangeListener();
        super.setOnHierarchyChangeListener(mPassThroughListener);
    }
    
    private int getAttribute(Context con) throws ClassNotFoundException, IllegalArgumentException, IllegalAccessException { 
    //use reflect to get styleable class.
    Field[] alFields = null; 
    ArrayList<Integer> alInts = new ArrayList<Integer>();
    int R_ID = 0;
    
    for (Class c : android.R.class.getClasses()) { 
         if (c.getName().indexOf("styleable") >= 0) { 
             alFields = Class.forName( con.getPackageName() + ".R$styleable" ).getFields();
    
         } 
     }
    for (Field f : alFields) { 
        Log.d("field name",f.getName());
        if (f.getName().equals("RadioGroup_checkedButton")) { 
            int[] ret = (int[])f.get(null);
            R_ID = ret[0];
        }
    
    }
    return R_ID;
    
    
    }
    
    //gets all RadioGroup R,android.internal.styleable.RadioGroup values
    private int[] getAttributes(Context con) throws IllegalAccessException, ClassNotFoundException { 
        //use reflect to get styleable class.
        Field[] alFields = null; 
        ArrayList<Integer> alInts = new ArrayList<Integer>();
        int[] ints = null;
        int count = 0;
        try {
            for (Class c : android.R.class.getClasses()) { 
                 if (c.getName().indexOf("styleable") >= 0) { 
                     Log.d("get Class Name Outer", c.getName());
                    //use reflection to access the resource class
                     alFields = Class.forName( con.getPackageName() + ".R$styleable" ).getFields();          
                 } 
    
             }
             if (alFields != null) 
                 {
                    Log.d("field numbers size", String.valueOf(alFields.length));
    
                    for (Field field : alFields) { 
    
                     Class<?> targetType = field.getType();
                     Log.d("field type", field.getType().toString());
                     if (targetType.equals(Integer.TYPE) && targetType.isPrimitive()) { 
                         //alInts.add((Integer)field);
                         Object objectValue = (Integer)field.getInt(null);
                         //Object objectValue = (Integer)targetType.newInstance(); 
                         alInts.add((Integer)objectValue);
                         count++;
                     }
                     ints = new int[count];
                     for (int i=0;i<alInts.size();i++) { 
                         ints[i] = alInts.get(i);
                     }
                 }
    
             }
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (ClassNotFoundException e) { 
            e.printStackTrace();
        }
        return ints;
    
    
        }
    
    public void check(int id) {
        // don't even bother
        if (id != -1 && (id == mCheckedId)) {
            return;
        }
        if (mCheckedId != -1) {
            setCheckedStateForView(mCheckedId, false);
        }
        if (id != -1) {
            setCheckedStateForView(id, true);
        }
        activeRadioButton = (RadioButton) findViewById(id);
        activeRadioButton.setChecked(true);
        setCheckedId(id);
    }
    
    public void setOnCheckedChangeListener(RadioGroupColumns.OnCheckedChangeListener onCheckedChangeListener) {
        mOnCheckedChangeListener = (OnCheckedChangeListener) onCheckedChangeListener;
    }
    
    private void setCheckedId(int id) {
        mCheckedId = id;
        if (mOnCheckedChangeListener != null) {
            mOnCheckedChangeListener.onCheckedChanged(this, mCheckedId);
        }
    }
    
    private void setCheckedStateForView(int viewId, boolean checked) {
        View checkedView = findViewById(viewId);
        if (!RadioButton.class.isAssignableFrom(checkedView.getClass()) && checkedView != null) { 
            TableRow row = (TableRow) checkedView;
            for (int j=0;j<row.getChildCount();j++) { 
                RadioButton button = (RadioButton) row.getChildAt(j);
                if (button.isChecked() && button != null) { 
                    button.setChecked(checked);
                }
            }
        }
        if (checkedView != null && checkedView instanceof RadioButton) {
            ((RadioButton) checkedView).setChecked(checked);
        }
    }
    
    /*
     * (non-Javadoc)
     * 
     * @see android.widget.TableLayout#addView(android.view.View, int,
     * android.view.ViewGroup.LayoutParams)
     */
    @Override
    public void addView(View child, int index,
            android.view.ViewGroup.LayoutParams params) {
        super.addView(child, index, params);
        setChildrenOnClickListener((TableRow) child);
    }
    
    /*
     * (non-Javadoc)
     * 
     * @see android.widget.TableLayout#addView(android.view.View,
     * android.view.ViewGroup.LayoutParams)
     */
    @Override
    public void addView(View child, android.view.ViewGroup.LayoutParams params) {
        super.addView(child, params);
        setChildrenOnClickListener((TableRow) child);
    }
    
    private void setChildrenOnClickListener(TableRow tr) {
        final int c = tr.getChildCount();
        for (int i = 0; i < c; i++) {
            final View v = tr.getChildAt(i);
            if (v instanceof RadioButton) {
                v.setOnClickListener(this);
            }
        }
    }
    
    public int getCheckedRadioButtonId() {
        if (activeRadioButton != null) {
            return activeRadioButton.getId();
        }
    
        return -1;
    }
    
    public interface OnCheckedChangeListener {
    
        public void onCheckedChanged(RadioGroupColumns group, 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 android.view.ViewGroup.OnHierarchyChangeListener {
        private android.view.ViewGroup.OnHierarchyChangeListener mOnHierarchyChangeListener;
    
        /**
         * {@inheritDoc}
         */
        @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
        public void onChildViewAdded(View parent, View child) {
            if (parent == RadioGroupColumns.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((com.assistek.ediary.RadioButton.OnCheckedChangeListener) mChildOnCheckedChangeListener);
            }
    
            if (mOnHierarchyChangeListener != null) {
                mOnHierarchyChangeListener.onChildViewAdded(parent, child);
            }
        }
    
        /**
         * {@inheritDoc}
         */
        public void onChildViewRemoved(View parent, View child) {
            if (parent == RadioGroupColumns.this
                    && child instanceof RadioButton) {
                ((RadioButton) child).setOnCheckedChangeListener(null);
            }
    
            if (mOnHierarchyChangeListener != null) {
                mOnHierarchyChangeListener.onChildViewRemoved(parent, child);
            }
        }
    }
    
     }
    

    Here is the code adding the radio buttons to the extended radiogroup:

        private void setupRadioButtonAnswers() {
        ArrayList<HolderAnswer> listAnswers = GlobalVars.questionHolders[GlobalVars.arrayRowNumber]
                .getListAnswers();
        ArrayList<ArrayList<HolderAnswer>> listAnswersSorted = new ArrayList<ArrayList<HolderAnswer>>();
        ArrayList<TableRow> alTableRows = new ArrayList<TableRow>();
    
        int NumberInColumns = (int) Math.floor(listAnswers.size() / NUMBER_OF_COLUMNS);
        // make higher number of answers on the right
        if (listAnswers.size() % NUMBER_OF_COLUMNS > 0)
            NumberInColumns++;
    
        for (int i = 0; i < NumberInColumns; i++) {
            TableRow row = new TableRow(this);
            TableRow.LayoutParams lp = new TableRow.LayoutParams(
                    TableRow.LayoutParams.WRAP_CONTENT);
            row.setLayoutParams(lp);
            alTableRows.add(row);
        }
    
        int count = 0;
    
        // sort by row
        /*
         * a[0] = "Question 1"
           a[1] = "Question 2"
           a[2] = "Question 3"
           a[3] = "Question 4"
           a[4] = "Question 5"
           a[5] = "Question 6"
           a[6] = "Question 7"
    
           sorted to:
    
           a[0] = "Question 1"   a[1] = "Question 5"
           a[2] = "Question 2"   a[3] = "Question 6"
           a[4] = "Question 3"   a[5] = "Question 7"
           a[6] = "Question 4"
         */
    
        // initialize the ArrayLists in listAnswersSorted
        int numRows = listAnswers.size() / NUMBER_OF_COLUMNS + 1;
        for (int i = 0; i < numRows; i += 1) {
            listAnswersSorted.add(new ArrayList<HolderAnswer>());
        }
    
        // calculate column index where the "step" happens
        int step = listAnswers.size() % NUMBER_OF_COLUMNS;
    
        // loop through and add elements to listAnswersSorted
        int index = 0;
        int row = 0;
        int col = 0;
        while (index < listAnswers.size()) {
            listAnswersSorted.get(row).add(listAnswers.get(index));
    
            int rows = col < step ? numRows : numRows - 1;
            row += 1;
            if (row == rows) {
            row = 0;
            col += 1;
            }
            index += 1;
        }
    
    
        row = 0;
        int columncount = 1;
        for (ArrayList<HolderAnswer> sortedArrayList : listAnswersSorted) {
            for (HolderAnswer answer : sortedArrayList) {
    
                final RadioButton button = new RadioButton(this);
                button.setTag(answer.getRecID());
                button.setId(GlobalVars.getLatestId());
                button.setTextColor(Color.BLACK);
                GlobalVars.setupText(con, button, answer.getTextID());
    
                button.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        button.setEnabled(false);
                        handlerReenableView.sendEmptyMessageDelayed(button.getId(), 1000);
    
                        button.setChecked(true);
                        radioGroup.check(button.getId());
                    }
                });
    
    
                button.setLayoutParams(new TableRow.LayoutParams(columncount));
                alTableRows.get(row).addView(button);
    
                if (columncount==NUMBER_OF_COLUMNS) { 
                    columncount = 1;
                    radioGroup.addView(alTableRows.get(row));
                    alTableRows.get(row).setOnClickListener(new View.OnClickListener() {
    
                        @Override
                        public void onClick(View v) {
    
                            for(int k=0;k<((TableRow) v).getChildCount();k++) { 
                                TableRow row = (TableRow) v;
                                for (int l=0;l<row.getChildCount();l++) { 
                                    RadioButton tableButton =  (RadioButton) row.getChildAt(l);
                                    if (tableButton.isChecked) { 
                                        radioGroup.check(tableButton.getId());
                                    }
                                }
                            }
                        }
    
                    });
    
                }
    
                else { 
                    columncount++;
                }
                //if (row=NumberInColumns)
                count++;
    
            }
    
            if (count == listAnswers.size()) { 
                radioGroup.addView(alTableRows.get(row));
            }
            row++;
    
        }
    
    
    
        radioGroup.setOnCheckedChangeListener(new RadioGroupColumns.OnCheckedChangeListener() {
                    @Override
                    public void onCheckedChanged(RadioGroupColumns group, int checkedId) {
                        Log.d("We're here",String.valueOf(checkedId));
                        if (checkedId == -1) {
                            for (int i = 0; i < radioGroup.getChildCount(); i++) {
                                TableRow row = (TableRow)radioGroup.getChildAt(i); 
                                for (int j=0;j<row.getChildCount();j++) { 
                                    if (RadioButton.class.isAssignableFrom(row.getChildAt(j).getClass())) {
                                        ((RadioButton) row.getChildAt(j)).setChecked(false);
                                    }
                                }
                            }
                        } else {
                            for (int i = 0; i < radioGroup.getChildCount(); i++) {
                                TableRow row = (TableRow)radioGroup.getChildAt(i); 
                                for (int j=0;j<row.getChildCount();j++) { 
                                    if (RadioButton.class.isAssignableFrom(row.getChildAt(j).getClass()) 
                                            && row.getChildAt(j).getId() != -1) {
                                        ((RadioButton) row.getChildAt(j)).setChecked(false);
                                    }
                                }
    
                            }
    
                            RadioButton checkedRadioButton = (RadioButton) radioGroup.findViewById(checkedId);
                            checkedRadioButton.setChecked(true);
                            Log.d("checkedID onchecked Change()", String.valueOf(radioGroup.getCheckedRadioButtonId()));
                        }
                    }
    
                });
    
    }
    
    0 讨论(0)
  • 2020-11-27 07:57

    I'm sure your question has been answered by now, but here is another take on it. With this code you can wrap your radio buttons into any layout you want (you don't need a radio group at all in fact). Also I would suggest using linear layouts to make the columns/rows you need.

    My code is based on @infografnet and @lostdev (also thanks @Neromancer for the Compound Button suggestion!)

    public class AdvRadioGroup {
        public interface OnButtonCheckedListener {
            void onButtonChecked(CompoundButton button);
        }
    
        private final List<CompoundButton> buttons;
        private final View.OnClickListener onClick = new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                setChecked((CompoundButton) v);
            }
        };
    
        private OnButtonCheckedListener listener;
        private CompoundButton lastChecked;
    
    
        public AdvRadioGroup(View view) {
            buttons = new ArrayList<>();
            parseView(view);
        }
    
        private void parseView(final View view) {
            if(view instanceof CompoundButton) {
                buttons.add((CompoundButton) view);
                view.setOnClickListener(onClick);
            } else if(view instanceof ViewGroup) {
                final ViewGroup group = (ViewGroup) view;
                for (int i = 0; i < group.getChildCount();i++) {
                    parseView(group.getChildAt(i));
                }
            }
        }
    
        public List<CompoundButton> getButtons() { return buttons; }
    
        public CompoundButton getLastChecked() { return lastChecked; }
    
        public void setChecked(int index) { setChecked(buttons.get(index)); }
    
        public void setChecked(CompoundButton button) {
            if(button == lastChecked) return;
    
            for (CompoundButton btn : buttons) {
                btn.setChecked(false);
            }
    
            button.setChecked(true);
    
            lastChecked = button;
    
            if(listener != null) {
                listener.onButtonChecked(button);
            }
        }
    
        public void setOnButtonCheckedListener(OnButtonCheckedListener listener) { this.listener = listener; }
    }
    

    Usage (with included listener):

    AdvRadioGroup group = new AdvRadioGroup(findViewById(R.id.YOUR_VIEW));
    group.setOnButtonCheckedListener(new AdvRadioGroup.OnButtonCheckedListener() {
        @Override
        public void onButtonChecked(CompoundButton button) {
            // do fun stuff here!
        }
    });
    

    Bonus: You can get the last checked button, the list of entire buttons, and you can check any button by index with this!

    0 讨论(0)
提交回复
热议问题