Android单选按钮取消选择

5

该应用程序是一个步进序列应用程序,其中包含16个具有8个按钮的单选按钮组。它工作得很好,除了一旦选择了一个按钮组,我就无法将其关闭,除非我使用已创建的清除按钮来清除所有单选按钮组。我想要添加的是一些代码,当再次选择所选单选按钮时,它会像切换开关一样简单地关闭。我尝试使用切换开关,但是那种方法出现了其他问题。以下是两次尝试,但都只让我停止使用按钮。

final RadioGroup radioGroup1 = (RadioGroup) findViewById(R.id.RadioGroup1);
RadioButton D1 = (RadioButton) findViewById(R.id.RadioButtonD1);

Button D1 = (Button) findViewById(R.id.RadioButtonD1);
D1.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick (View v){
        PdBase.sendFloat("D1", 74);
        int selectedTypeId = radioGroup1.getCheckedRadioButtonId();
        RadioButton D1 = (RadioButton) findViewById(selectedTypeId);
        if (D1 != null) // This will be null if none of the radio buttons are selected
            radioGroup1.clearCheck();
        PdBase.sendFloat("D1", 0);
    }
});

RadioButton lC1 = (RadioButton) findViewById(R.id.RadioButtonlowC1);
lC1.setOnClickListener(new View.OnClickListener() {
    public void onClick (View v) {
        int selectedTypeId = radioGroup1.getCheckedRadioButtonId();

        RadioButton lC1 = (RadioButton) findViewById(R.id.RadioButtonlowC1);
        if (selectedTypeId == -1) {
            PdBase.sendFloat("lC1", 72);
        }
        else if (selectedTypeId == R.id.RadioButtonlowC1) {
            radioGroup1.clearCheck();
            PdBase.sendFloat("lC1", 0);
        }
    }
});

为什么不给每个组添加一个关闭按钮呢? - Philip Sheard
1
这通常不是 RadioButtons 的工作方式,也不是人们预期的。你应该向你的组添加一个像 none 这样的 RadioButton - codeMagic
我可以这样做,但由于它是单声部的,我希望在每个组中仅选择一个。 - A B
为每个组设置一个清除按钮是可行的,但不太实用。 - A B
1
无论如何,每个组中只能选择一个。这就是单选按钮的工作原理。从设计角度来看,您的问题在于您有效地使用未选择任何按钮作为额外条件,而您无法切换它。 - Philip Sheard
可能是取消选中单选按钮的重复问题。 - spaaarky21
7个回答

25

最近我也有同样的需求——创建一个单选框组,可以通过再次点击选择的项来取消选择。我发现无法使用监听器实现这个功能,但是我可以通过使用自定义的RadioButton来实现,像这样...

public class ToggleableRadioButton extends RadioButton {
    // Implement necessary constructors

    @Override
    public void toggle() {
        if(isChecked()) {
            if(getParent() instanceof RadioGroup) {
                ((RadioGroup)getParent()).clearCheck();
            }
        } else {
            setChecked(true);
        }
    }
}

请注意,按钮的切换方式取决于其当前状态——即在按钮上调用setChecked(true)与在组中调用clearCheck()不同。如果在两种情况下都使用setChecked(),则刚刚取消选择的按钮不能立即重新选择——RadioGroup 中的逻辑似乎会立即取消选择它。

要使用此按钮,请在您的布局 XML 中将 <RadioButton> 标签替换为 <your.package.ToggleableRadioButton>


在实现构造函数时出现错误 LOGCAT:- ToggleableRadioButton.<init> [class android.content.Context,interface android.util.AttributeSet] - Arbaz.in

7

我刚刚使用了来自@spaaarky21的答案。

我的完整代码如下,它可以正常运行!

Java类

public class ToggleableRadioButton extends RadioButton {


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

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

    public ToggleableRadioButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public ToggleableRadioButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    public void toggle() {
        if(isChecked()) {
            if(getParent() instanceof RadioGroup) {
                ((RadioGroup)getParent()).clearCheck();
            }
        } else {
            setChecked(true);
        }
    }
}

对于XML布局

<com.smart_dent.adapters.ToggleableRadioButton android:id="@+id/tejido_blando_perfil_convexo"
                                 android:layout_width="wrap_content"
                                 android:layout_height="wrap_content"
                                 android:text="@string/tejido_blando_convexo_label" />

在这种情况下,你只需要更改包名。这很容易找到,就在Java类文件的顶部(如果你是从Android Studio创建它的)。

5
实际上可以通过监听器来实现,但需要使用一个 OnTouchListener,它会在按钮状态改变之前触发,而不是通常的 OnClickListener。以下代码对我有效:
View.OnTouchListener radioButtonOnTouchListener = new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (((RadioButton) v).isChecked()) {
            // If the button was already checked, uncheck them all
            radioGroup.clearCheck();
            // Prevent the system from re-checking it
            return true;
        }
        return false;
    }
};
radioButton1.setOnTouchListener(radioButtonOnTouchListener);
radioButton2.setOnTouchListener(radioButtonOnTouchListener);

其中radioGroupradioButton1radioButton2的父级元素。


onTouch()是相当底层的。看起来这会取消选择按钮,使其无法响应除了轻触/点击之外的手势。 - spaaarky21
嗯,说得好,@spaaarky21。我想我们还应该检查事件的类型是否为ACTION_DOWN。虽然,经过测试,我还没有能够触发任何异常情况。 - wamfous

4

从@spaaarky21的回答进行编辑

@Override
public void toggle() {
    if (isChecked()) {
        if (getParent() instanceof RadioGroup) {
            ((RadioGroup) getParent()).clearCheck();
        } 
        // add else here when a single radioButton without radioGroup
        else {
            setChecked(false);
        }
    } else {
        setChecked(true);
    }
}

1
这也能完成工作:
public final class ToggleAbleRadioButton extends AppCompatRadioButton {
  public ToggleAbleRadioButton(final Context context, final AttributeSet attrs) {
    super(context, attrs);
  }

  @Override public void toggle() {
    setChecked(!isChecked());
  }
}

不起作用,如果您检查两次,则不会再次检查,因为此代码在appCompatRadioButoon中 - if(mBroadcasting){ 返回; } - blay

0
您可以使用布尔值来切换按钮的开关。
在代码中添加一个布尔值:
var radioButton1IsSelected = false

然后为按钮设置 onClickListener:
radioButton1.setOnClickListener {
        radioButton1IsSelected = !radioButton1IsSelected
        radioButton1.isChecked = radioButton1IsSelected
    }

0
这是自定义的ToggleableRadioButton的Kotlin版本,可以在不使用RadioGroup的情况下取消选中。
class ToggleableRadioButton constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) :
        AppCompatRadioButton(context, attrs, defStyleAttr) {

    constructor(context: Context) : this(context, null)

    constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)

    override fun toggle() {
        isChecked = !isChecked
    }
}

默认设置下,即super.toggle()不会取消选中,因为它受RadioButton.java的显式控制。

RadioButton Toggle Source Code

根据文档所述,如果单选按钮已经被选中,切换操作将不会被调用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接