RadioGroup with two columns which have ten RadioButtons

后端 未结 12 1996
难免孤独
难免孤独 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:

    
        
            
        
    
    
    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;
        }
    }
    

提交回复
热议问题