如何从不同的LinearLayouts分组RadioButton?

时间:2012-05-05 10:34:18

标签: android radio-button android-linearlayout radio-group

我想知道是否可以将每个RadioButton分组到唯一的RadioGroup中 保持相同的结构。我的结构看起来像这样:

  • LinearLayout_main
    • LinearLayout_1
      • RadioButton1
    • LinearLayout_2
      • RadioButton2
    • LinearLayout_3
      • RadioButton3

如您所见,现在每个RadioButton都是不同LinearLayout的孩子。我尝试使用下面的结构,但它不起作用:

  • radioGroup中
    • LinearLayout_main
      • LinearLayout_1
        • RadioButton1
      • LinearLayout_2
        • RadioButton2
      • LinearLayout_3
        • RadioButton3

22 个答案:

答案 0 :(得分:37)

Google / Android的好人似乎认为,当您使用RadioButtons时,您不需要Android UI /布局系统的其他方面带来的灵活性。简单地说:他们不希望你嵌套布局和单选按钮。叹息。

所以你必须解决这个问题。这意味着你必须自己实现单选按钮。

这真的不太难。在你的onCreate()中,用你自己的onClick()设置你的RadioButtons,这样当它们被激活时,它们setChecked(true)并对其他按钮执行相反的操作。例如:

class FooActivity {

    RadioButton m_one, m_two, m_three;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...
        m_one = (RadioButton) findViewById(R.id.first_radio_button);
        m_two = (RadioButton) findViewById(R.id.second_radio_button);
        m_three = (RadioButton) findViewById(R.id.third_radio_button);

        m_one.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                m_one.setChecked(true);
                m_two.setChecked(false);
                m_three.setChecked(false);
            }
        });

        m_two.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                m_one.setChecked(false);
                m_two.setChecked(true);
                m_three.setChecked(false);
            }
        });

        m_three.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                m_one.setChecked(false);
                m_two.setChecked(false);
                m_three.setChecked(true);
            }
        });

        ...     
    } // onCreate() 

}

是的,我知道 - 老派。但它的确有效。祝你好运!

答案 1 :(得分:25)

使用我创建的这个类。它将在您的层次结构中找到所有可检查的子项。

import java.util.ArrayList;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Checkable;
import android.widget.LinearLayout;

public class MyRadioGroup extends LinearLayout {

private ArrayList<View> mCheckables = new ArrayList<View>();

public MyRadioGroup(Context context) {
    super(context);
}

public MyRadioGroup(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
}

public MyRadioGroup(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
}

@Override
public void addView(View child, int index,
        android.view.ViewGroup.LayoutParams params) {
    super.addView(child, index, params);
    parseChild(child);
}

public void parseChild(final View child)
{
    if(child instanceof Checkable)
    {
        mCheckables.add(child);
        child.setOnClickListener(new OnClickListener() {

            public void onClick(View v) {
                for(int i = 0; i < mCheckables.size();i++)
                {
                    Checkable view = (Checkable) mCheckables.get(i);
                    if(view == v)
                    {
                        ((Checkable)view).setChecked(true);
                    }
                    else
                    {
                        ((Checkable)view).setChecked(false);
                    }
                }
            }
        });
    }
    else if(child instanceof ViewGroup)
    {
        parseChildren((ViewGroup)child);
    }
}

public void parseChildren(final ViewGroup child)
{
    for (int i = 0; i < child.getChildCount();i++)
    {
        parseChild(child.getChildAt(i));
    }
}
}

答案 2 :(得分:17)

好吧,我写了这个简单的课程。

就这样使用它:

// add any number of RadioButton resource IDs here
GRadioGroup gr = new GRadioGroup(this, 
    R.id.radioButton1, R.id.radioButton2, R.id.radioButton3);

GRadioGroup gr = new GRadioGroup(rb1, rb2, rb3);
// where RadioButton rb1 = (RadioButton) findViewById(R.id.radioButton1);
// etc.

例如,您可以在Activity的onCreate()中调用它。无论您点击哪个RadioButton,其他都将取消选中。此外,如果RadioButtons中的某些RadioGroup位于某些package pl.infografnet.GClasses; import java.util.ArrayList; import java.util.List; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewParent; import android.widget.RadioButton; import android.widget.RadioGroup; public class GRadioGroup { List<RadioButton> radios = new ArrayList<RadioButton>(); /** * Constructor, which allows you to pass number of RadioButton instances, * making a group. * * @param radios * One RadioButton or more. */ public GRadioGroup(RadioButton... radios) { super(); for (RadioButton rb : radios) { this.radios.add(rb); rb.setOnClickListener(onClick); } } /** * Constructor, which allows you to pass number of RadioButtons * represented by resource IDs, making a group. * * @param activity * Current View (or Activity) to which those RadioButtons * belong. * @param radiosIDs * One RadioButton or more. */ public GRadioGroup(View activity, int... radiosIDs) { super(); for (int radioButtonID : radiosIDs) { RadioButton rb = (RadioButton)activity.findViewById(radioButtonID); if (rb != null) { this.radios.add(rb); rb.setOnClickListener(onClick); } } } /** * This occurs everytime when one of RadioButtons is clicked, * and deselects all others in the group. */ OnClickListener onClick = new OnClickListener() { @Override public void onClick(View v) { // let's deselect all radios in group for (RadioButton rb : radios) { ViewParent p = rb.getParent(); if (p.getClass().equals(RadioGroup.class)) { // if RadioButton belongs to RadioGroup, // then deselect all radios in it RadioGroup rg = (RadioGroup) p; rg.clearCheck(); } else { // if RadioButton DOES NOT belong to RadioGroup, // just deselect it rb.setChecked(false); } } // now let's select currently clicked RadioButton if (v.getClass().equals(RadioButton.class)) { RadioButton rb = (RadioButton) v; rb.setChecked(true); } } }; } 内,则无关紧要。

这是班级:

{{1}}

答案 3 :(得分:7)

以下是基于@lostdev solutionRadioGroup实施的解决方案。它是一个RadioGroup,经过修改后可以与嵌套在子布局中的RadioButtons(或其他CompoundButtons)一起使用。

import android.content.Context;
import android.os.Build;
import android.support.annotation.IdRes;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.LinearLayout;
import android.widget.RadioButton;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * This class is a replacement for android RadioGroup - it supports
 * child layouts which standard RadioGroup doesn't.
 */
public class RecursiveRadioGroup extends LinearLayout {

    public interface OnCheckedChangeListener {
        void onCheckedChanged(RecursiveRadioGroup group, @IdRes int checkedId);
    }

    /**
     * For generating unique view IDs on API < 17 with {@link #generateViewId()}.
     */
    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);

    private CompoundButton checkedView;

    private CompoundButton.OnCheckedChangeListener childOnCheckedChangeListener;

    /**
     * When this flag is true, onCheckedChangeListener discards events.
     */
    private boolean mProtectFromCheckedChange = false;

    private OnCheckedChangeListener onCheckedChangeListener;

    private PassThroughHierarchyChangeListener mPassThroughListener;

    public RecursiveRadioGroup(Context context) {
        super(context);
        setOrientation(HORIZONTAL);
        init();
    }

    public RecursiveRadioGroup(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public RecursiveRadioGroup(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        childOnCheckedChangeListener = new CheckedStateTracker();
        mPassThroughListener = new PassThroughHierarchyChangeListener();

        super.setOnHierarchyChangeListener(mPassThroughListener);
    }

    @Override
    public void setOnHierarchyChangeListener(OnHierarchyChangeListener listener) {
        mPassThroughListener.mOnHierarchyChangeListener = listener;
    }

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

        // checks the appropriate radio button as requested in the XML file
        if (checkedView != null) {
            mProtectFromCheckedChange = true;
            setCheckedStateForView(checkedView, true);
            mProtectFromCheckedChange = false;
            setCheckedView(checkedView);
        }
    }

    @Override
    public void addView(View child, int index, ViewGroup.LayoutParams params) {
        parseChild(child);

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

    private void parseChild(final View child) {
        if (child instanceof CompoundButton) {
            final CompoundButton checkable = (CompoundButton) child;

            if (checkable.isChecked()) {
                mProtectFromCheckedChange = true;
                if (checkedView != null) {
                    setCheckedStateForView(checkedView, false);
                }
                mProtectFromCheckedChange = false;
                setCheckedView(checkable);
            }
        } else if (child instanceof ViewGroup) {
            parseChildren((ViewGroup) child);
        }
    }

    private void parseChildren(final ViewGroup child) {
        for (int i = 0; i < child.getChildCount(); i++) {
            parseChild(child.getChildAt(i));
        }
    }

    /**
     * <p>Sets the selection to the radio button whose identifier is passed in
     * parameter. Using -1 as the selection identifier clears the selection;
     * such an operation is equivalent to invoking {@link #clearCheck()}.</p>
     *
     * @param view the radio button to select in this group
     * @see #getCheckedItemId()
     * @see #clearCheck()
     */
    public void check(CompoundButton view) {
        if(checkedView != null) {
            setCheckedStateForView(checkedView, false);
        }

        if(view != null) {
            setCheckedStateForView(view, true);
        }

        setCheckedView(view);
    }

    private void setCheckedView(CompoundButton view) {
        checkedView = view;

        if(onCheckedChangeListener != null) {
            onCheckedChangeListener.onCheckedChanged(this, checkedView.getId());
        }
    }

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

    /**
     * <p>Returns the identifier of the selected radio button in this group.
     * Upon empty selection, the returned value is -1.</p>
     *
     * @return the unique id of the selected radio button in this group
     * @attr ref android.R.styleable#RadioGroup_checkedButton
     * @see #check(CompoundButton)
     * @see #clearCheck()
     */
    @IdRes
    public int getCheckedItemId() {
        return checkedView.getId();
    }

    public CompoundButton getCheckedItem() {
        return checkedView;
    }

    /**
     * <p>Clears the selection. When the selection is cleared, no radio button
     * in this group is selected and {@link #getCheckedItemId()} returns
     * null.</p>
     *
     * @see #check(CompoundButton)
     * @see #getCheckedItemId()
     */
    public void clearCheck() {
        check(null);
    }

    /**
     * <p>Register a callback to be invoked when the checked radio button
     * changes in this group.</p>
     *
     * @param listener the callback to call on checked state change
     */
    public void setOnCheckedChangeListener(RecursiveRadioGroup.OnCheckedChangeListener listener) {
        onCheckedChangeListener = listener;
    }

    /**
     * Generate a value suitable for use in {@link #setId(int)}.
     * This value will not collide with ID values generated at build time by aapt for R.id.
     *
     * @return a generated ID value
     */
    public static int generateViewId() {
        for (; ; ) {
            final int result = sNextGeneratedId.get();
            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
            int newValue = result + 1;
            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
            if (sNextGeneratedId.compareAndSet(result, newValue)) {
                return result;
            }
        }
    }

    private class CheckedStateTracker implements CompoundButton.OnCheckedChangeListener {

        @Override
        public void onCheckedChanged(CompoundButton view, boolean b) {
            if (mProtectFromCheckedChange) {
                return;
            }

            mProtectFromCheckedChange = true;
            if (checkedView != null) {
                setCheckedStateForView(checkedView, false);
            }
            mProtectFromCheckedChange = false;

            int id = view.getId();
            setCheckedView(view);
        }
    }

    private class PassThroughHierarchyChangeListener implements OnHierarchyChangeListener {

        private OnHierarchyChangeListener mOnHierarchyChangeListener;

        @Override
        public void onChildViewAdded(View parent, View child) {
            if (child instanceof CompoundButton) {
                int id = child.getId();

                if (id == View.NO_ID) {
                    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
                        child.setId(generateViewId());
                    } else {
                        child.setId(View.generateViewId());
                    }
                }

                ((CompoundButton) child).setOnCheckedChangeListener(childOnCheckedChangeListener);

                if (mOnHierarchyChangeListener != null) {
                    mOnHierarchyChangeListener.onChildViewAdded(parent, child);
                }
            } else if(child instanceof ViewGroup) {
                // View hierarchy seems to be constructed from the bottom up,
                // so all child views are already added. That's why we
                // manually call the listener for all children of ViewGroup.
                for(int i = 0; i < ((ViewGroup) child).getChildCount(); i++) {
                    onChildViewAdded(child, ((ViewGroup) child).getChildAt(i));
                }
            }
        }

        @Override
        public void onChildViewRemoved(View parent, View child) {
            if (child instanceof RadioButton) {
                ((CompoundButton) child).setOnCheckedChangeListener(null);
            }

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

}

您可以在布局中使用它,就像使用常规RadioGroup一样,但它也适用于嵌套的RadioButton视图:

<RecursiveRadioGroup
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="16dp"
    android:layout_marginBottom="16dp"
    android:layout_marginLeft="16dp"
    android:layout_marginRight="16dp"
    android:orientation="horizontal">

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="vertical">

        <RadioButton
            android:id="@+id/rbNotEnoughProfileInfo"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Not enough profile information"/>

        <RadioButton
            android:id="@+id/rbNotAGoodFit"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Not a good fit"/>

        <RadioButton
            android:id="@+id/rbDatesNoLongerAvailable"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Dates no longer available"/>

    </LinearLayout>

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:orientation="vertical">

        <RadioButton
            android:id="@+id/rbOther"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Other"/>

        <android.support.v7.widget.AppCompatEditText
            android:id="@+id/etReason"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@+id/tvMessageError"
            android:textSize="15sp"
            android:gravity="top|left"
            android:hint="Tell us more"
            android:padding="16dp"
            android:background="@drawable/edit_text_multiline_background"/>
    </LinearLayout>

</RecursiveRadioGroup>

答案 4 :(得分:4)

感叹。真怪Android缺乏这样的基本功能。

从@ScottBiggs答案改编而成,这是使用Kotlin的最短方法:

var currentSelected = button1
listOf<RadioButton>(
    button1, button2, button3, ...
).forEach {
    it.setOnClickListener { _ ->
        currentSelected.isChecked = false
        currentSelected = it
        currentSelected.isChecked = true
    }
}

答案 5 :(得分:3)

我创建了这两种方法来解决这个问题。你所要做的就是传递RadioButtons所在的ViewGroup(可以是RadioGroup,LinearLayout,RelativeLayout等),并且它独家设置OnClick事件,也就是说,每当一个RadioButton是ViewGroup的子节点时(选择任何嵌套级别),其他未选中。它适用于任意数量的嵌套布局。

public class Utils {
    public static void setRadioExclusiveClick(ViewGroup parent) {
        final List<RadioButton> radios = getRadioButtons(parent);

        for (RadioButton radio: radios) {
            radio.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    RadioButton r = (RadioButton) v;
                    r.setChecked(true);
                    for (RadioButton r2:radios) {
                        if (r2.getId() != r.getId()) {
                            r2.setChecked(false);
                        }
                    }

                }
            });
        }
    }

    private static List<RadioButton> getRadioButtons(ViewGroup parent) {
        List<RadioButton> radios = new ArrayList<RadioButton>();
        for (int i=0;i < parent.getChildCount(); i++) {
            View v = parent.getChildAt(i);
            if (v instanceof RadioButton) {
                radios.add((RadioButton) v);
            } else if (v instanceof ViewGroup) {
                List<RadioButton> nestedRadios = getRadioButtons((ViewGroup) v);
                radios.addAll(nestedRadios);
            }
        }
        return radios;
    }
}

活动中的用法如下:

ViewGroup parent = findViewById(R.id.radios_parent);
Utils.setRadioExclusiveClick(parent);

答案 6 :(得分:2)

我编写了自己的无线电组类,允许包含嵌套的单选按钮。看看这个。如果您发现错误,请告诉我。

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.LinearLayout;

/**
 * This class is used to create a multiple-exclusion scope for a set of compound
 * buttons. Checking one compound button that belongs to a group unchecks any
 * previously checked compound button within the same group. Intially, all of
 * the compound buttons are unchecked. While it is not possible to uncheck a
 * particular compound button, the group can be cleared to remove the checked
 * state. Basically, this class extends functionality of
 * {@link android.widget.RadioGroup} because it doesn't require that compound
 * buttons are direct childs of the group. This means you can wrap compound
 * buttons with other views. <br>
 * <br>
 * 
 * <b>IMPORTATNT! Follow these instruction when using this class:</b><br>
 * 1. Each direct child of this group must contain one compound button or be
 * compound button itself.<br>
 * 2. Do not set any "on click" or "on checked changed" listeners for the childs
 * of this group.
 */
public class CompoundButtonsGroup extends LinearLayout {

 private View checkedView;
 private OnCheckedChangeListener listener;
 private OnHierarchyChangeListener onHierarchyChangeListener;

 private OnHierarchyChangeListener onHierarchyChangeListenerInternal = new OnHierarchyChangeListener() {

  @Override
  public final void onChildViewAdded(View parent, View child) {
   notifyHierarchyChanged(null);
   if (CompoundButtonsGroup.this.onHierarchyChangeListener != null) {
    CompoundButtonsGroup.this.onHierarchyChangeListener.onChildViewAdded(
      parent, child);
   }
  }

  @Override
  public final void onChildViewRemoved(View parent, View child) {
   notifyHierarchyChanged(child);
   if (CompoundButtonsGroup.this.onHierarchyChangeListener != null) {
    CompoundButtonsGroup.this.onHierarchyChangeListener.onChildViewRemoved(
      parent, child);
   }
  }
 };

 public CompoundButtonsGroup(Context context) {
  super(context);
  init();
 }

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

 public CompoundButtonsGroup(Context context, AttributeSet attrs, int defStyle) {
  super(context, attrs, defStyle);
  init();
 }

 private void init() {
  super.setOnHierarchyChangeListener(this.onHierarchyChangeListenerInternal);
 }

 @Override
 public final void setOnHierarchyChangeListener(OnHierarchyChangeListener listener) {
  this.onHierarchyChangeListener = listener;
 }

 /**
  * Register a callback to be invoked when the checked view changes in this
  * group.
  * 
  * @param listener
  *            the callback to call on checked state change.
  */
 public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {
  this.listener = listener;
 }

 /**
  * Returns currently selected view in this group. Upon empty selection, the
  * returned value is null.
  */
 public View getCheckedView() {
  return this.checkedView;
 }

 /**
  * Returns index of currently selected view in this group. Upon empty
  * selection, the returned value is -1.
  */
 public int getCheckedViewIndex() {
  return (this.checkedView != null) ? indexOfChild(this.checkedView) : -1;
 }

 /**
  * Sets the selection to the view whose index in group is passed in
  * parameter.
  * 
  * @param index
  *            the index of the view to select in this group.
  */
 public void check(int index) {
  check(getChildAt(index));
 }

 /**
  * Clears the selection. When the selection is cleared, no view in this
  * group is selected and {@link #getCheckedView()} returns null.
  */
 public void clearCheck() {
  if (this.checkedView != null) {
   findCompoundButton(this.checkedView).setChecked(false);
   this.checkedView = null;
   onCheckedChanged();
  }
 }

 private void onCheckedChanged() {
  if (this.listener != null) {
   this.listener.onCheckedChanged(this.checkedView);
  }
 }

 private void check(View child) {
  if (this.checkedView == null || !this.checkedView.equals(child)) {
   if (this.checkedView != null) {
    findCompoundButton(this.checkedView).setChecked(false);
   }

   CompoundButton comBtn = findCompoundButton(child);
   comBtn.setChecked(true);

   this.checkedView = child;
   onCheckedChanged();
  }
 }

 private void notifyHierarchyChanged(View removedView) {
  for (int i = 0; i < getChildCount(); i++) {
   View child = getChildAt(i);
   child.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View v) {
     check(v);
    }
   });
   CompoundButton comBtn = findCompoundButton(child);
   comBtn.setClickable(comBtn.equals(child));
  }

  if (this.checkedView != null && removedView != null
    && this.checkedView.equals(removedView)) {
   clearCheck();
  }
 }

 private CompoundButton findCompoundButton(View view) {
  if (view instanceof CompoundButton) {
   return (CompoundButton) view;
  }

  if (view instanceof ViewGroup) {
   for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
    CompoundButton compoundBtn = findCompoundButton(((ViewGroup) view)
      .getChildAt(i));
    if (compoundBtn != null) {
     return compoundBtn;
    }
   }
  }

  return null;
 }

 /**
  * Interface definition for a callback to be invoked when the checked view
  * changed in this group.
  */
 public interface OnCheckedChangeListener {

  /**
   * Called when the checked view has changed.
   * 
   * @param checkedView
   *            newly checked view or null if selection was cleared in the
   *            group.
   */
  public void onCheckedChanged(View checkedView);
 }

}

答案 7 :(得分:2)

你需要做两件事:

  1. 使用mListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
  2. 制作自定义行视图工具Checkable
  3. 所以我认为更好的解决方案是在你的内部LinearLayout中实现Checkable :(感谢daichan4649,来自他的链接,https://gist.github.com/daichan4649/5245378,我接受了下面粘贴的所有代码)

    CheckableLayout.java

    package daichan4649.test;
    
    import android.content.Context;
    import android.util.AttributeSet;
    import android.view.View;
    import android.widget.Checkable;
    import android.widget.LinearLayout;
    
    public class CheckableLayout extends LinearLayout implements Checkable {
    
        private static final int[] CHECKED_STATE_SET = { android.R.attr.state_checked };
    
        public CheckableLayout(Context context) {
            super(context, null);
        }
    
        public CheckableLayout(Context context, AttributeSet attrs) {
            super(context, attrs, 0);
        }
    
        public CheckableLayout(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }
    
        private boolean checked;
    
        @Override
        public boolean isChecked() {
            return checked;
        }
    
        @Override
        public void setChecked(boolean checked) {
            if (this.checked != checked) {
                this.checked = checked;
                refreshDrawableState();
    
                for (int i = 0; i < getChildCount(); i++) {
                    View child = getChildAt(i);
                    if (child instanceof Checkable) {
                        ((Checkable) child).setChecked(checked);
                    }
                }
            }
        }
    
        @Override
        public void toggle() {
            setChecked(!checked);
        }
    
        @Override
        protected int[] onCreateDrawableState(int extraSpace) {
            final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
            if (isChecked()) {
                mergeDrawableStates(drawableState, CHECKED_STATE_SET);
            }
            return drawableState;
        }
    }
    

    inflater_list_column.xml

    <?xml version="1.0" encoding="utf-8"?>
    <daichan4649.test.CheckableLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/check_area"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical">
    
        <TextView
            android:id="@+id/text"
            android:layout_width="0dip"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_weight="1"
            android:gravity="center_vertical" />
    
        <RadioButton
            android:id="@+id/radio"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:clickable="false"
            android:focusable="false"
            android:focusableInTouchMode="false" />
    
    </daichan4649.test.CheckableLayout>
    

    TestFragment.java

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    
        View view = inflater.inflate(R.layout.fragment_test, container, false);
    
        // 表示データ
        List<String> dataList = new ArrayList<String>();
    
        // 初期選択位置
        int initSelectedPosition = 3;
    
        // リスト設定
        TestAdapter adapter = new TestAdapter(getActivity(), dataList);
        ListView listView = (ListView) view.findViewById(R.id.list);
        listView.setAdapter(adapter);
        listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
        listView.setItemChecked(initSelectedPosition, true);
    
        listView.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                // 選択状態を要素(checkable)へ反映
                Checkable child = (Checkable) parent.getChildAt(position);
                child.toggle();
            }
        });
        return view;
    }
    
    private static class TestAdapter extends ArrayAdapter<String> {
    
        private LayoutInflater inflater;
    
        public TestAdapter(Context context, List<String> dataList) {
            super(context, 0, dataList);
            inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        }
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            final ViewHolder holder;
            if (convertView == null) {
                convertView = inflater.inflate(R.layout.inflater_list_column, null);
                holder = new ViewHolder();
                holder.text = (TextView) convertView.findViewById(R.id.text);
                convertView.setTag(holder);
            } else {
                holder = (ViewHolder) convertView.getTag();
            }
    
            // bindData
            holder.text.setText(getItem(position));
            return convertView;
        }
    }
    
    private static class ViewHolder {
        TextView text;
    }
    

答案 8 :(得分:1)

已经有 20 个答案了,但我敢说我认为我有最好的答案。

这使用视图数据绑定,因此您要做的第一件事就是将其添加到模块的 build.gradle

android {
    dataBinding {
        enabled = true
    }
}

然后您可以使用您想要的视图层次结构进行布局,例如:

fancy_radio_button.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>
        <variable name="title" type="String"/>
        <variable name="description" type="String"/>
        <variable name="checked" type="boolean"/>
        <variable name="buttonId" type="int"/>
    </data>

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="wrap_content"
        android:layout_height="match_parent">

        <!--  clickable=false since we implement the click listener on the whole view  -->
        <RadioButton
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:clickable="false"
            android:text="@{title}"
            android:checked="@{checked}"/>

        <TextView
            android:text="@{description}"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>

        <View
            android:layout_width="match_parent"
            android:layout_height="24dp" />

    </LinearLayout>

</layout>

这可以是您想要的样子,只需确保在 android:clickable="false" 上设置 RadioButton,并在需要的地方使用数据绑定变量。

该布局由此类处理:

FancyRadioBroup.java

package com.example.app;

import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.RadioGroup;

import com.example.app.FancyRadioButtonBinding;

import java.util.ArrayList;

public class FancyRadioGroup extends RadioGroup implements View.OnClickListener {

    private final ArrayList<FancyRadioButtonBinding> radioButtons = new ArrayList<>();
    private OnSelectionChangedListener selectionChangedListener;

    public FancyRadioGroup(Context context) {
        super(context);
    }

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

    public void setOnSelectionChangedListener(OnSelectionChangedListener selectionChangedListener) {
        this.selectionChangedListener = selectionChangedListener;
    }

    public int addOption(String title, String description) {
        // inflate view and get binding
        FancyRadioButtonBinding buttonBinding = FancyRadioButtonBinding.inflate(LayoutInflater.from(getContext()), this, true);
        // set title and description
        buttonBinding.setTitle(title);
        buttonBinding.setDescription(description);
        // give the button an id (just use the index)
        buttonBinding.setButtonId(radioButtons.size());
        // set the root view's tag to the binding, so we can get the binding from the view
        View root = buttonBinding.getRoot();
        root.setTag(buttonBinding);
        // set click listener on the whole view, so we can click anywhere
        root.setOnClickListener(this);
        radioButtons.add(buttonBinding);
        // return button id to caller, so they know what was clicked
        return buttonBinding.getButtonId();
    }

    @Override
    public void onClick(View v) {
        for (FancyRadioButtonBinding binding : radioButtons) {
                binding.setChecked(v.getTag() == binding);
        }
        if (selectionChangedListener != null) {
            selectionChangedListener.onSelectionChanged(getSelected());
        }
    }

    public int getSelected() {
        for (FancyRadioButtonBinding binding : radioButtons) {
            if (binding.getChecked()) {
                return binding.getButtonId();
            }
        }
        return -1;
    }

    public interface OnSelectionChangedListener {
        void onSelectionChanged(int buttonId);
    }

}

要使用,只需将 FancyRadioGroup 添加到您的视图中:

activity_foo.xml

<com.example.app.FancyRadioGroup android:id="@+id/radio_group"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

然后添加您的选项:

FooActivity.java

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    FancyRadioGroup radioGroup = findViewById(R.id.radio_group);
    radioGroup.addOption("The First One", "This option is recommended for users who like the number one.");
    radioGroup.addOption("The Second One", "For advanced users. Larger than one.");
    radioGroup.setOnSelectionChangedListener(this::doSomething);
}

private void doSomething(int id) {
    Toast.makeText(this, "selected: "+id, Toast.LENGTH_SHORT).show();
}

答案 9 :(得分:1)

没有什么能阻止你实现布局结构(RadioGroup实际上是LinearLayout的子类),但你不应该这样做。首先,你创建一个4级深度的结构(使用另一种布局结构,你可以优化它);第二,如果你的RadioButtons不是RadioGroup的直接子项,选择的唯一一个项目在组中将无法正常工作。这意味着,如果您从该布局中选择Radiobutton,然后选择另一个RadioButton,则最终会选择两个RadioButtons,而不是最后选择的一个。

如果您在该布局中解释您想要做什么,我可以向您推荐替代方案。

答案 10 :(得分:1)

您可以使用此简单的RadioGroup扩展代码。将所有布局/视图/图像与RadioButton一起放入其中,它将起作用。

它包含选择回调,该回调返回选定的RadioButton及其索引,您可以通过索引或ID编程设置选择:

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RadioButton;
import android.widget.RadioGroup;

import java.util.ArrayList;

public class EnhancedRadioGroup extends RadioGroup implements View.OnClickListener {

    public interface OnSelectionChangedListener {
        void onSelectionChanged(RadioButton radioButton, int index);
    }

    private OnSelectionChangedListener selectionChangedListener;
    ArrayList<RadioButton> radioButtons = new ArrayList<>();

    public EnhancedRadioGroup(Context context) {
        super(context);
    }

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

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        if (changed) {
            getRadioButtons();
        }
    }

    private void getRadioButtons() {
        radioButtons.clear();
        checkForRadioButtons(this);
    }

    private void checkForRadioButtons(ViewGroup viewGroup) {
        if (viewGroup == null) {
            return;
        }
        for (int i = 0; i < viewGroup.getChildCount(); i++) {
            View v = viewGroup.getChildAt(i);
            if (v instanceof RadioButton) {
                v.setOnClickListener(this);
                // store index of item
                v.setTag(radioButtons.size());
                radioButtons.add((RadioButton) v);
            }
            else if (v instanceof ViewGroup) {
                checkForRadioButtons((ViewGroup)v);
            }
        }
    }

    public RadioButton getSelectedItem() {
        if (radioButtons.isEmpty()) {
            getRadioButtons();
        }
        for (RadioButton radioButton : radioButtons) {
            if (radioButton.isChecked()) {
                return radioButton;
            }
        }
        return null;
    }

    public void setOnSelectionChanged(OnSelectionChangedListener selectionChangedListener) {
        this.selectionChangedListener = selectionChangedListener;
    }

    public void setSelectedById(int id) {
        if (radioButtons.isEmpty()) {
            getRadioButtons();
        }
        for (RadioButton radioButton : radioButtons) {
            boolean isSelectedRadioButton = radioButton.getId() == id;
            radioButton.setChecked(isSelectedRadioButton);
            if (isSelectedRadioButton && selectionChangedListener != null) {
                selectionChangedListener.onSelectionChanged(radioButton, (int)radioButton.getTag());
            }
        }
    }

    public void setSelectedByIndex(int index) {
        if (radioButtons.isEmpty()) {
            getRadioButtons();
        }
        if (radioButtons.size() > index) {
            setSelectedRadioButton(radioButtons.get(index));
        }
    }

    @Override
    public void onClick(View v) {
        setSelectedRadioButton((RadioButton) v);
    }

    private void setSelectedRadioButton(RadioButton rb) {
        if (radioButtons.isEmpty()) {
            getRadioButtons();
        }
        for (RadioButton radioButton : radioButtons) {
            radioButton.setChecked(rb == radioButton);
        }
        if (selectionChangedListener != null) {
            selectionChangedListener.onSelectionChanged(rb, (int)rb.getTag());
        }
    }
}

在布局xml中使用它:

    <path.to.your.package.EnhancedRadioGroup>
       Layouts containing RadioButtons/Images/Views and other RadioButtons
    </path.to.your.package.EnhancedRadioGroup>

要注册到回调,请执行以下操作:

        enhancedRadioGroupInstance.setOnSelectionChanged(new EnhancedRadioGroup.OnSelectionChangedListener() {
            @Override
            public void onSelectionChanged(RadioButton radioButton, int index) {

            }
        });

答案 11 :(得分:1)

我的0.02美元基于@infografnet和@lostdev(也感谢@Neromancer的复合按钮建议!)

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

用法(包含侦听器):

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

奖励:您可以获取最后一个选中的按钮,整个按钮的列表,您可以使用索引按索引检查任何按钮!

答案 12 :(得分:1)

此解决方案尚未发布,因此发布:

步骤0:创建let image = UIImage(named: "frame_1") var ciimage = CIImage(image: image!) print("\(ciimage!.extent.width) x \(ciimage!.extent.height)") // at this point it returns "480.0 x 360.0" that is ok ciimage = ciimage!.clamping(to: CGRect(x: 50, y: 50, width: 480.0, height: 360.0)) print("\(ciimage!.extent.width) x \(ciimage!.extent.height)") //now it returns two strange values: "1.79769313486232e+308 x 1.79769313486232e+308" 作为全局变量。

第1步:为单选按钮创建CompountButton previousCheckedCompoundButton;

OnCheckedChangedListener

步骤3:向所有单选按钮添加监听器:

CompoundButton.OnCheckedChangeListener onRadioButtonCheckedListener = new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            if (!isChecked) return;
            if (previousCheckedCompoundButton != null) {
                previousCheckedCompoundButton.setChecked(false);
                previousCheckedCompoundButton = buttonView;
            } else {
                previousCheckedCompoundButton = buttonView;
            }
        }
    };

多数民众赞成!!你做完了。

答案 13 :(得分:1)

我遇到了同样的问题,因为我想在两个不同的linearlayout中放置4个不同的单选按钮,这些布局将是无线电组的孩子。为了实现RadioGroup中的期望行为,我重载了addView函数

这是解决方案

public class AgentRadioGroup extends RadioGroup
{

    public AgentRadioGroup(Context context) {
        super(context);
    }

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

    @Override
    public void onViewAdded(View child) {
        if( child instanceof ViewGroup)
        {
            ViewGroup viewGroup = (ViewGroup) child;
            for(int i=0; i<viewGroup.getChildCount(); i++)
            {
                View subChild = viewGroup.getChildAt(i);
                if( subChild instanceof ViewGroup )
                {
                    onViewAdded(subChild);
                }
                else
                {
                    if (subChild instanceof RadioButton) {
                        super.onViewAdded(subChild);
                    }
                }
            }
        }
        if (child instanceof RadioButton)
        {
            super.onViewAdded(child);
        }
    }
}

答案 14 :(得分:0)

这是@Infografnet解决方案的修改版本。它简单易用。

RadioGroupHelper group = new RadioGroupHelper(this,R.id.radioButton1,R.id.radioButton2); group.radioButtons.get(0).performClick(); //programmatically

只需复制并粘贴

即可
package com.qamar4p.farmer.ui.custom;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.RadioButton;

public class RadioGroupHelper {

    public List<CompoundButton> radioButtons = new ArrayList<>();

    public RadioGroupHelper(RadioButton... radios) {
        super();
        for (RadioButton rb : radios) {
            add(rb);
        }
    }

    public RadioGroupHelper(Activity activity, int... radiosIDs) {
        this(activity.findViewById(android.R.id.content),radiosIDs);
    }

    public RadioGroupHelper(View rootView, int... radiosIDs) {
        super();
        for (int radioButtonID : radiosIDs) {
            add((RadioButton)rootView.findViewById(radioButtonID));
        }
    }

    private void add(CompoundButton button){
        this.radioButtons.add(button);
        button.setOnClickListener(onClickListener);
    }

    View.OnClickListener onClickListener = v -> {
        for (CompoundButton rb : radioButtons) {
            if(rb != v) rb.setChecked(false);
        }
    };
}

答案 15 :(得分:0)

如答案所示,解决方案是一个简单的自定义hack。这是我在Kotlin中的简约版本。

import android.widget.RadioButton

class SimpleRadioGroup(private val radioButtons: List<RadioButton>) {

    init {
        radioButtons.forEach {
            it.setOnClickListener { clickedButton ->
                radioButtons.forEach { it.isChecked = false }
                (clickedButton as RadioButton).isChecked = true
            }
        }
    }

    val checkedButton: RadioButton?
        get() = radioButtons.firstOrNull { it.isChecked }
}

然后,您只需要在活动的onCreate或片段的onViewCreated中执行以下操作即可:

SimpleRadioGroup(listOf(radio_button_1, radio_button_2, radio_button_3))

答案 16 :(得分:0)

这是我在Kotlin上针对带有RadioButton的自定义布局的解决方案。

tipInfoContainerFirst.radioButton.isChecked = true

var prevSelected = tipInfoContainerFirst.radioButton
prevSelected.isSelected = true

listOf<RadioButton>(
    tipInfoContainerFirst.radioButton,
    tipInfoContainerSecond.radioButton,
    tipInfoContainerThird.radioButton,
    tipInfoContainerForth.radioButton,
    tipInfoContainerCustom.radioButton
).forEach {
    it.setOnClickListener { _it ->
    if(!it.isSelected) {
        prevSelected.isChecked = false
        prevSelected.isSelected = false
        it.radioButton.isSelected = true
        prevSelected = it.radioButton
    }
  }
}

答案 17 :(得分:0)

    int currentCheckedRadioButton = 0;
    int[] myRadioButtons= new int[6];
    myRadioButtons[0] = R.id.first;
    myRadioButtons[1] = R.id.second;
    //..
    for (int radioButtonID : myRadioButtons) {
        findViewById(radioButtonID).setOnClickListener(
                    new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (currentCheckedRadioButton != 0)
                    ((RadioButton) findViewById(currentCheckedRadioButton)).setChecked(false);
                currentCheckedRadioButton = v.getId();

            }
        });
    }

答案 18 :(得分:0)

我遇到了同样的问题,我必须使用“单选”按钮来设置性别,并且都带有图片和文字,因此我尝试使用以下方法解决该问题。

xml文件:

<RadioGroup
       android:layout_marginTop="40dp"
       android:layout_marginEnd="23dp"
       android:id="@+id/rgGender"
       android:layout_width="match_parent"
       android:layout_below="@id/tvCustomer"
       android:orientation="horizontal"
       android:layout_height="wrap_content">

       <LinearLayout
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:orientation="vertical"
           android:gravity="center_horizontal"
           android:layout_weight="1">
       <RadioButton
           android:id="@+id/rbMale"
           android:layout_width="80dp"
           android:layout_height="60dp"
           android:background="@drawable/male_radio_btn_selector"
           android:button="@null"
           style="@style/RadioButton.Roboto.20sp"/>

           <TextView
               android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:text="Male"
               style="@style/TextView.RobotoLight.TxtGrey.18sp"
               android:layout_margin="0dp"
               android:textSize="@dimen/txtsize_20sp"/>
       </LinearLayout>
       <LinearLayout
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:orientation="vertical"
           android:gravity="center_horizontal"
           android:layout_weight="1">
       <RadioButton
           android:layout_weight="1"
           android:gravity="center"
           android:id="@+id/rbFemale"
           android:layout_width="80dp"
           android:layout_height="60dp"
           android:button="@null"
           android:background="@drawable/female_radio_btn_selector"
           style="@style/RadioButton.Roboto.20sp"
           android:textColor="@color/light_grey"/>
           <TextView
               android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:text="Female"
               android:layout_margin="0dp"
               style="@style/TextView.RobotoLight.TxtGrey.18sp"
               android:textSize="@dimen/txtsize_20sp"/>
       </LinearLayout>
       <LinearLayout
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:orientation="vertical"
           android:gravity="center_horizontal"
           android:layout_weight="1">
       <RadioButton
           android:layout_weight="1"
           android:gravity="center"
           android:id="@+id/rbOthers"
           android:layout_width="80dp"
           android:layout_height="60dp"
           android:button="@null"
           android:background="@drawable/other_gender_radio_btn_selector"
           style="@style/RadioButton.Roboto.20sp"/>
          <TextView
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:text="Other"
              android:layout_margin="0dp"
              style="@style/TextView.RobotoLight.TxtGrey.18sp"
              android:textSize="@dimen/txtsize_20sp"/>
      </LinearLayout>
   </RadioGroup>

在Java文件中: 我在所有3个单选按钮上设置了setOnCheckedChangeListener,并如下所述覆盖了方法,对我来说它工作正常。

@Override
    public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
   switch (compoundButton.getId()){
       case R.id.rbMale:
           if(rbMale.isChecked()){
               rbMale.setChecked(true);
               rbFemale.setChecked(false);
               rbOther.setChecked(false);
           }
           break;
       case R.id.rbFemale:
           if(rbFemale.isChecked()){
               rbMale.setChecked(false);
               rbFemale.setChecked(true);
               rbOther.setChecked(false);
           }
           break;
       case R.id.rbOthers:
           if(rbOther.isChecked()){
               rbMale.setChecked(false);
               rbFemale.setChecked(false);
               rbOther.setChecked(true);
           }
           break;

   }
    }

答案 19 :(得分:0)

MixedCompoundButtonGroup 为您做到!

MixedCompoundButtonGroup gist

fun setAll() {
    for (i in 0 until childCount) {
        val child = getChildAt(i)
        setCompoundButtonListener(child)
    }
}  


private fun setCompoundButtonListener(view: View?) {
    if (view == null) return
    if (view is CompoundButton) {
        view.setOnCheckedChangeListener(compoundButtonCheckedChangedListener)
    } else if (view is ViewGroup && view !is RadioGroup) { // NOT RadioGroup!
        for (i in 0 until view.childCount) {
            setCompoundButtonListener(view.getChildAt(i))
        }
    }
}

private fun initCompoundButtonListener() {
    compoundButtonCheckedChangedListener = CompoundButton.OnCheckedChangeListener { compoundButton, isChecked ->
        setChecked(compoundButton, isChecked)
    }
}

private fun setChecked(compoundButton: CompoundButton, isChecked: Boolean) {
    if (isChecked.not()) return
    if (currentCompoundButton != null) {
        currentCompoundButton!!.isChecked = false
        currentCompoundButton = compoundButton
    } else {
        currentCompoundButton = compoundButton
    }
    checkedChangedListener?.onCheckedChanged(currentCompoundButton!!)
}

答案 20 :(得分:0)

虽然这可能是一个较旧的主题,但我想快速分享我写的简单hacky代码..它不适合所有人,也可以做一些改进..

使用此代码的情况??
此代码适用于具有原始问题或类似问题的布局的人,在我的情况下,如下所示。这本身就是我正在使用的Dialog。

  • LinLayout_Main
    • LinLayout_Row1
      • ImageView的
      • 单选按钮
    • LinLayout_Row2
      • ImageView的
      • 单选按钮
    • LinLayout_Row3
      • ImageView的
      • 单选按钮

代码本身做了什么?
此代码将枚举“LinLayout_Main”的Child,并且对于每个“LinearLayout”的子项,它将枚举任何RadioButtons的View。

只需查看父“LinLayout_Main”并查找任何Child LinearLayouts中的任何RadioButtons。

<强> MyMethod_ShowDialog
将显示带有XML布局文件的对话框,同时还要查找为其找到的每个RadioButton设置“setOnClickListener”

<强> MyMethod_ClickRadio
将以“MyMethod_ShowDialog”的方式循环每个RadioButton,但不是设置“setOnClickListener”而是设置“setChecked(false)”以清除每个RadioButton,然后作为最后一步将“setChecked(false)”传递给调用的RadioButton点击事件。

public void MyMethod_ShowDialog(final double tmpLat, final double tmpLng) {
        final Dialog dialog = new Dialog(actMain);
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
        dialog.setContentView(R.layout.layout_dialogXML);

        final LinearLayout tmpLayMain = (LinearLayout)dialog.findViewById(R.id.LinLayout_Main);
        if (tmpLayMain!=null) {
            // Perform look for each child of main LinearLayout
            int iChildCount1 = tmpLayMain.getChildCount();
            for (int iLoop1=0; iLoop1 < iChildCount1; iLoop1++){
                View tmpChild1 = tmpLayMain.getChildAt(iLoop1);
                if (tmpChild1 instanceof LinearLayout) {
                    // Perform look for each LinearLayout child of main LinearLayout
                    int iChildCount2 = ((LinearLayout) tmpChild1).getChildCount();
                    for (int iLoop2=0; iLoop2 < iChildCount2; iLoop2++){
                        View tmpChild2 = ((LinearLayout) tmpChild1).getChildAt(iLoop2);
                        if (tmpChild2 instanceof RadioButton) {
                            ((RadioButton) tmpChild2).setOnClickListener(new RadioButton.OnClickListener() {
                                public void onClick(View v) {
                                    MyMethod_ClickRadio(v, dialog);
                                }
                            });
                        }
                    }
                }
            }

            Button dialogButton = (Button)dialog.findViewById(R.id.LinLayout_Save);
            dialogButton.setOnClickListener(new Button.OnClickListener() {
                public void onClick(View v) {
                    dialog.dismiss();
                }
            });
        }
       dialog.show();
}


public void MyMethod_ClickRadio(View vRadio, final Dialog dDialog) {

        final LinearLayout tmpLayMain = (LinearLayout)dDialog.findViewById(R.id.LinLayout_Main);
        if (tmpLayMain!=null) {
            int iChildCount1 = tmpLayMain.getChildCount();
            for (int iLoop1=0; iLoop1 < iChildCount1; iLoop1++){
                View tmpChild1 = tmpLayMain.getChildAt(iLoop1);
                if (tmpChild1 instanceof LinearLayout) {
                    int iChildCount2 = ((LinearLayout) tmpChild1).getChildCount();
                    for (int iLoop2=0; iLoop2 < iChildCount2; iLoop2++){
                        View tmpChild2 = ((LinearLayout) tmpChild1).getChildAt(iLoop2);
                        if (tmpChild2 instanceof RadioButton) {
                            ((RadioButton) tmpChild2).setChecked(false);
                        }
                    }
                }
            }
        }

        ((RadioButton) vRadio).setChecked(true);
}

可能存在错误,从项目中复制并重命名为Voids / XML / ID

您还可以运行相同类型的循环以找出要检查的项目

答案 21 :(得分:-1)

尝试这种方式在RadioGroup中添加LinearLayout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical" >

    <RadioGroup
        android:id="@+id/radioGroup1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:weightSum="1" >

        <RadioButton
            android:id="@+id/radio0"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:checked="true"
            android:text="RadioButton" />

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

        <RadioButton
            android:id="@+id/radio2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="RadioButton" />
    </RadioGroup>
</LinearLayout>

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical" >

    <RadioGroup
        android:id="@+id/radioGroup2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:weightSum="1" >

        <RadioButton
            android:id="@+id/radio3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:checked="true"
            android:text="RadioButton" />

        <RadioButton
            android:id="@+id/radio4"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="RadioButton" />

        <RadioButton
            android:id="@+id/radio5"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="RadioButton" />
    </RadioGroup>
 </LinearLayout>
 </LinearLayout>