Android:如何使用切换按钮获取单选组?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2379527/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 05:37:20  来源:igfitidea点击:

Android: How to get a radiogroup with togglebuttons?

androidtogglebuttonbar

提问by Peterdk

I want a group of buttons where a user can choose one of them as option. It has to be a radiobuttongroup like behaviour, but I don't want the radio circle to be present. I just want the user to be able to toggle only one of the buttons.

我想要一组按钮,用户可以在其中选择其中一个作为选项。它必须是一个类似单选按钮组的行为,但我不希望出现单选圈。我只希望用户只能切换其中一个按钮。

I think I would need someting like a togglegroup.

我想我需要像togglegroup这样的东西。

Does something like this exist in Android?

Android中是否存在这样的东西?

回答by Wolf Paulus

I'd just re-usethe RadioGrouplike so: (please note the onClickattribute,i.e. a button click will trigger your Activity's onToggle(View)method.

我只是重复使用RadioGroup,像这样:(请注意onClick属性,即点击一个按钮会触发你的活动的onToggle(View)方法。

<RadioGroup android:id="@+id/toggleGroup"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="24dp"
            android:orientation="horizontal"
        >

    <ToggleButton android:id="@+id/btn_Letter"
                  android:layout_height="wrap_content"
                  android:layout_width="fill_parent"
                  android:layout_weight="1"
                  android:textSize="14sp"
                  android:textOn="Letter"
                  android:textOff="Letter"
                  android:onClick="onToggle"
                  android:checked="true"
            />
    <ToggleButton android:id="@+id/btn_A4"
                  android:layout_height="wrap_content"
                  android:layout_width="fill_parent"
                  android:layout_weight="1"
                  android:textSize="14sp"
                  android:textOn="A4"
                  android:textOff="A4"
                  android:onClick="onToggle"
            />
</RadioGroup>

In your Activity, or some place else, you can define a listener, e.g.

在您的 Activity 或其他地方,您可以定义一个侦听器,例如

static final RadioGroup.OnCheckedChangeListener ToggleListener = new RadioGroup.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(final RadioGroup radioGroup, final int i) {
            for (int j = 0; j < radioGroup.getChildCount(); j++) {
                final ToggleButton view = (ToggleButton) radioGroup.getChildAt(j);
                view.setChecked(view.getId() == i);
            }
        }
    };

and register it, for instance in onCreate():

并注册它,例如在onCreate()

@Override
 public void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     this.setContentView(R.layout.scan_settings);

     ((RadioGroup) findViewById(R.id.toggleGroup)).setOnCheckedChangeListener(ToggleListener);    
 }

finally in onToggle(View), you would do whatever needs to happen, specific to your app. and also call the RadioGroup's checkmethod, with the toggled view's id. Like so:

最后onToggle(View),你会做任何需要发生的事情,具体到你的应用程序。并使用切换视图的 id调用 RadioGroup 的check方法。像这样:

public void onToggle(View view) {
    ((RadioGroup)view.getParent()).check(view.getId());
    // app specific stuff ..
}

回答by dhaag23

You can use regular radio buttons and use an image for the RadioButton background and don't specify a text string:

您可以使用常规单选按钮并为 RadioButton 背景使用图像,而不指定文本字符串:

<RadioButton 
android:id="@+id/custom_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
    android:button="@null"
    android:background="@drawable/button_custom"
    />

For the background, use any drawable, but most likely you'll want to use a selector to be able to provide different images for the different states. The simplest version uses just two images:

对于背景,请使用任何可绘制对象,但很可能您希望使用选择器为不同的状态提供不同的图像。最简单的版本只使用两个图像:

<item android:state_checked="true" android:state_pressed="true"
      android:drawable="@drawable/custom_selected" />
<item android:state_checked="false" android:state_pressed="true"
      android:drawable="@drawable/custom_normal" />

<item android:state_checked="true" android:state_focused="true"
      android:drawable="@drawable/custom_selected" />
<item android:state_checked="false" android:state_focused="true"
      android:drawable="@drawable/custom_normal" />

<item android:state_checked="false" android:drawable="@drawable/custom_normal" />
<item android:state_checked="true" android:drawable="@drawable/custom_selected" />

With this, the radio button looks like a regular button (or rather, looks like whatever drawable you provided) and behaves like a radio button in a radio group.

有了这个,单选按钮看起来像一个普通按钮(或者更确切地说,看起来像你提供的任何可绘制的)并且表现得像一个单选按钮组中的单选按钮。

回答by Caspar Harmer

I tried all the methods outlined above and none really worked that well.

我尝试了上面列出的所有方法,但没有一个真正奏效。

Trying to hack a radiobutton to look like a real button looks bad.

试图破解一个单选按钮看起来像一个真正的按钮看起来很糟糕。

Eventually I just took the RadioGroup source code and Modified it to accept a ToggleButton rather than a RadioButton. Works really well!

最终我只是采用 RadioGroup 源代码并修改它以接受 ToggleButton 而不是 RadioButton。真的很好用!

Here is the source on Github: ToggleGroup

这是 Github 上的来源:ToggleGroup

Usage:

用法:

    <com.rapsacnz.ToggleGroup
    android:id="@+id/deal_detail_toolbar"
    android:layout_width="fill_parent"
    android:layout_height="60dip"
    android:layout_alignParentBottom="true"
    android:background="@drawable/bgnd_toggle_button">
    <ToggleButton
        android:id="@+id/b1"
        android:textOn="@string/tab_1_label"
        android:textOff="@string/tab_1_label"
        android:textSize="10sp"
        android:textColor="@color/tab_button_color"
        android:checked="true"
        android:layout_width="fill_parent"
        android:layout_height="60dp"
        android:layout_weight="1"
        android:drawableTop="@drawable/toggle_spotlight"
        android:drawablePadding="-5dp "
        android:gravity="bottom|center"
        android:paddingTop="10dp"
        android:paddingBottom="5dp"
        android:background="@drawable/bgnd_transparent" />
    <ToggleButton
        android:id="@+id/b2"
        android:textOn="@string/tab_2_label"
        android:textOff="@string/tab_2_label"
        android:textSize="10sp"
        android:textColor="@color/tab_button_color"
        android:checked="false"
        android:layout_width="fill_parent"
        android:layout_height="60dp"
        android:layout_weight="1"
        android:drawableTop="@drawable/toggle_browse"
        android:gravity="bottom|center"
        android:paddingTop="10dp"
        android:paddingBottom="5dp"
        android:background="@drawable/bgnd_transparent" />

    <ToggleButton
        android:id="@+id/b3"
        android:textOn="@string/tab_3_label"
        android:textOff="@string/tab_3_label"
        android:textSize="10sp"
        android:textColor="@color/tab_button_color"
        android:checked="false"
        android:layout_width="fill_parent"
        android:layout_height="60dp"
        android:layout_weight="1"
        android:drawableTop="@drawable/toggle_purchased"
        android:gravity="bottom|center"
        android:paddingTop="10dp"
        android:paddingBottom="5dp"
        android:background="@drawable/bgnd_transparent" />
</com.rapsacnz.ToggleGroup>

Hope this helps

希望这可以帮助

回答by Eng.Fouad

Here is how I managed to do it (no RadioGroupinvolved):

这是我设法做到的(不RadioGroup涉及):

private CompoundButton.OnCheckedChangeListener toggleListener = new CompoundButton.OnCheckedChangeListener()
{
    boolean avoidRecursions = false;

    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
    {
        if(avoidRecursions) return;
        avoidRecursions = true;

        // don't allow the un-checking
        if(!isChecked)
        {
            buttonView.setChecked(true);
            avoidRecursions = false;
            return;
        }

        // un-check the previous checked button
        if(buttonView != toggleButton1 && toggleButton1.isChecked()) toggleButton1.setChecked(false);
        else if(buttonView != toggleButton2 && toggleButton2.isChecked()) toggleButton2.setChecked(false);
        else if(buttonView != toggleButton3 && toggleButton3.isChecked()) toggleButton3.setChecked(false);
        else if(buttonView != toggleButton4 && toggleButton4.isChecked()) toggleButton4.setChecked(false);

        avoidRecursions = false;
    }
};

// ...

toggleButton1.setOnCheckedChangeListener(toggleListener);
toggleButton2.setOnCheckedChangeListener(toggleListener);
toggleButton3.setOnCheckedChangeListener(toggleListener);
toggleButton4.setOnCheckedChangeListener(toggleListener);

回答by Tiferet Cohen

I'm using Kotlin and I tried Wolf Paulus's answer and it didn't work well for me. I played around with it and was able to make it work in the following way: First, I removed the "onClick" from the xml:

我正在使用 Kotlin,我尝试了 Wolf Paulus 的答案,但对我来说效果不佳。我玩弄了它,并能够通过以下方式使其工作:首先,我从 xml 中删除了“onClick”:

    <RadioGroup android:id="@+id/toggleGroup"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="24dp"
            android:orientation="horizontal"
        >

    <ToggleButton android:id="@+id/btn_Letter"
                  android:layout_height="wrap_content"
                  android:layout_width="fill_parent"
                  android:layout_weight="1"
                  android:textSize="14sp"
                  android:textOn="Letter"
                  android:textOff="Letter"
                  android:checked="true"
            />
    <ToggleButton android:id="@+id/btn_A4"
                  android:layout_height="wrap_content"
                  android:layout_width="fill_parent"
                  android:layout_weight="1"
                  android:textSize="14sp"
                  android:textOn="A4"
                  android:textOff="A4"
            />
</RadioGroup>

I didn't use the ToggleListener, instead, inside the onCreate()I listened to each of the ToggleButtons I have:

我没有使用ToggleListener,而是在onCreate()我听过的每个ToggleButtons 中:

    btn_Letter.setOnClickListener { it -> onToggle(it) }
    btn_A4.setOnClickListener { it -> onToggle(it) }

And the most important part, the onToggle(btn: View)

而最重要的部分, onToggle(btn: View)

private fun onToggle(btn: View) {
    val radioGroup = (btn.parent as RadioGroup)
    for (index in 0 until radioGroup.childCount) {
        val child = radioGroup.getChildAt(index) as ToggleButton
        child.isChecked = child.id == btn.id
       // do what ever else you need to do
    }
}

This is it. I hope this helps.

就是这个。我希望这有帮助。

回答by user2287189

my solution achieves the same effect but without using the radiobuttons.

我的解决方案实现了相同的效果,但不使用单选按钮。

For the xml, first un "selector" in "@drawable/myselectorfile":

对于 xml,首先在“@drawable/myselectorfile”中取消“选择器”:

   <?xml version="1.0" encoding="UTF-8"?>
      <selector
           xmlns:android="http://schemas.android.com/apk/res/android">
       <item android:state_checked="false"
        android:drawable="@drawable/icon_off" />
       <item android:state_checked="true"
        android:drawable="@drawable/icon_on" />
   </selector>

un file for items of my listview:

我的列表视图项目的 un 文件:

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

    <TextView
        android:id="@+id/txtInfo"
        android:layout_width="140dp"
        android:layout_height="wrap_content"
        android:paddingTop="15dip" />

   <ToggleButton
       android:id="@+id/BtnToggle"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_alignParentRight="true"
       android:layout_alignParentTop="true"
       android:layout_marginRight="14dp"
       android:background="@drawable/toggle_style"
       android:padding="10dip"
       android:textOff=""
       android:textOn="" 
       android:focusable="false"/>  

   </LinearLayout>

and my listview :

和我的列表视图:

   <?xml version="1.0" encoding="utf-8"?>
      <ListView xmlns:android="http://schemas.android.com/apk/res/android"
       android:id="@+id/lv_lista"
       android:layout_width="match_parent"
       android:layout_height="match_parent" >
    </ListView> 

in the oncreate methode:

在 oncreate 方法中:

     lista.setOnItemClickListener(new OnItemClickListener() { 
        @SuppressWarnings("deprecation")
        @Override
        public void onItemClick(AdapterView<?> pariente, View view, int    posicion, long id) {
        @SuppressWarnings("unused")
        ListEntity elegido = (ListEntity) pariente.getItemAtPosition(posicion); 

        varToggle = (ToggleButton) view.findViewById(R.id.BtnToggle);
        varToggle.setChecked(true);

                    // showDialog(0); // dialog optional

                   //restart btn's
                  reStart(posicion);
        }
        });

in the Activity class:

在活动类中:

         @Override
         protected Dialog onCreateDialog(int id){
            Dialog dialogo = crearDialogoConfirmacion(); 
            return dialogo; 
         }

         public void reStart(int posicion){ 

         for(int j=0;j<lista.getCount();j++)
             {
               View vista = lista.getChildAt(j);
               ToggleButton varToggle2 = (ToggleButton) vista.findViewById(R.id.BtnToggle);
               if(j != posicion){ varToggle2.setChecked(false); }              
              } 
          }

回答by arekolek

I did it with LinearLayout instead of RadioGroup, using ButterKnife:

我用 LinearLayout 而不是 RadioGroup 做到了,使用 ButterKnife:

@BindViews({R.id.one, R.id.two, R.id.three})
List<ToggleButton> toggleGroup;

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    ButterKnife.bind(this, view);
}

@OnClick({R.id.one, R.id.two, R.id.three})
public void toggle(ToggleButton selected) {
    if (selected.isChecked()) {
        // Deselect other buttons
        for (ToggleButton button : toggleGroup) {
            if (button.getId() != selected.getId()) {
                button.setChecked(false);
            }
        }
    } else {
        // Disallow deselecting the current button
        selected.toggle();
    }
}

回答by LanDenLabs

Using any container ViewGroupadd your CompoundButtons(CheckBox, RadioButton, Switch, SwitchCompat, ToggleButton) and then inside your onCheckedChangedcall a utility function to clear the other buttons.

使用任何容器ViewGroup添加您的复合按钮(CheckBox、RadioButton、Switch、SwitchCompat、ToggleButton),然后在您的onCheckedChanged 中调用一个实用程序函数来清除其他按钮。

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

            <ToggleButton
                android:id="@+id/toggle_btn1"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:textOff="Off1"
                android:textOn="On1" />

            <View
                android:layout_width="2dp"
                android:layout_height="match_parent"
                android:layout_margin ="8dp"
                android:background="#ffff" />

            <ToggleButton
                android:id="@+id/toggle_btn2"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:textOff="Off2"
                android:textOn="On2" />
        </LinearLayout>

Inside your onCheckedChanged, deal with the state change and call the utility method to clear the other children. The following supports all view container groups which are derived from ViewGroupand allows you to mixed non-CompoundButtonobjects in the container. Since you often have a onCheckedChangedcallback already, there only new code is to call the utility function.

在您的onCheckedChanged 中,处理状态更改并调用实用程序方法来清除其他子项。以下支持所有派生自ViewGroup 的视图容器组,并允许您在容器中混合非CompoundButton对象。由于您通常已经有一个onCheckedChanged回调,因此只有新代码是调用实用程序函数。

@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
    int id = buttonView.getId();
    switch (id) {
        case R.id.toggle_btn1:
            if (isChecked) {
                doBtn1Action();
                doRadioGroupChange((ViewGroup)buttonView.getParent(), id);
            }
            break;
        case R.id.toggle_btn2:
            if (isChecked) {
                doBtn2Action();;
                doRadioGroupChange((ViewGroup)buttonView.getParent(), id);
            }
            break;

And here is the utility function to clear children.

这是清除子项的效用函数。

/**
 * Emulate radioGroup and clear buttons which don't match checkedId.
 * @param viewGroup
 * @param checkedId
 */
private static void doRadioGroupChange(final ViewGroup viewGroup, final int checkedId) {
    for (int rgIdx = 0; rgIdx < viewGroup.getChildCount(); rgIdx++) {
        View child = viewGroup.getChildAt(rgIdx);
        if (child instanceof  CompoundButton) {
            final CompoundButton view = (CompoundButton) viewGroup.getChildAt(rgIdx);
            view.setChecked(view.getId() == checkedId);
        }
    }
}

回答by HimalayanCoder

public void OnTabSelected(View v){
        RadioGroup radioGroup = (RadioGroup)v.getParent();
        for (int j = 0; j < radioGroup.getChildCount(); j++) {
            ToggleButton toggleButton = (ToggleButton) radioGroup.getChildAt(j);
            toggleButton.setChecked(v.getId() == toggleButton.getId());
        }
    }

回答by gc986

Kotlin version:

科特林版本:

for(index in 0..(radioGroup.childCount-1))
                (radioGroup.getChildAt(index) as ToggleButton).isChecked = false