【问题标题】:Android: How to get a radiogroup with togglebuttons?Android:如何获得带有切换按钮的无线电组?
【发布时间】:2011-01-23 16:26:36
【问题描述】:

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

我想我需要一个类似于切换组的东西。

Android 中是否存在类似的东西?

【问题讨论】:

  • 仍然打开,但我使用了另一种方法,不需要无线电组。
  • 你用了什么方法?

标签: android togglebuttonbar


【解决方案1】:

所以您希望一次只能选择一个按钮? 如果您不显示单选按钮,用户如何知道她选择了什么?

您可以使用 RadioButton 和 RadioGroup,但我不知道您是否可以轻松生成外观更适合您的应用的自定义单选按钮。但是,如果您可以扩展单选按钮本身并覆盖 draw 方法,或者查看可以将哪些孩子的按钮集成到 radiogroup 中,那么它应该是可能的。也许您可以为您的视图实现一个特殊的界面,然后将您的一些自定义按钮连接到一个单选组中。

【讨论】:

    【解决方案2】:

    您可以使用常规单选按钮并使用图像作为 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"
        />
    

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

    <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" />
    

    这样,单选按钮看起来像一个常规按钮(或者更确切地说,看起来像您提供的任何可绘制对象)并且其行为类似于单选组中的单选按钮。

    【讨论】:

    • 但是如果我希望这些按钮适合父宽度,而背景被均匀拉伸并居中(如 ImageView 的 scaleType="centerInside")?
    • 这个解决方案是最干净的。它在保持RadioButton 功能的同时实现ToggleButton 的可见效果。 @Wolf Paulus 的解决方案有效,但它允许组处于所有按钮都关闭的状态。
    【解决方案3】:

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

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

    最终,我只使用了 RadioGroup 源代码并将其修改为接受 ToggleButton 而不是 RadioButton。效果很好!

    这里是 Github 上的来源:ToggleGroup

    用法:

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

    希望对你有帮助

    【讨论】:

    • 您在此处发布的代码有一个小问题,如果切换按钮@+id/b1(或任何其他切换按钮)打开(选中)并且您再次按下按钮将关闭(未选中)。单选组中的单选按钮不存在此行为。为了解决这个问题,我将类方法 onCheckedChanged 更改为:
    • // 防止无限递归 if (mProtectFromCheckedChange) { return; } int id = buttonView.getId(); mProtectFromCheckedChange = true; if(mCheckedId == id){ //如果强制检查相同 setCheckedStateForView(mCheckedId, true); } else if (mCheckedId != -1) { setCheckedStateForView(mCheckedId, false); } mProtectFromCheckedChange = false; setCheckedId(id);
    • 谢谢!我可能已经在我的生产代码中自己完成了这个 - 忘记在这里更改它。
    • 我很想使用它,但它似乎有一些问题:1)尝试使用该应用程序会在它膨胀时产生异常原因:android.view .InflateException: Binary XML file line #80: Error inflating class... 2) 不能在 LayoutEditor 中使用它(我在 init() 调用中添加了 isEditMode() 检查,但它们没有帮助 - 可以' t 实例化课程,但我怀疑这是由#1 引起的。3)上述更改似乎也不存在于那里。非常感谢你写它!
    • 这是相当古老的代码 - 您可能需要获取 RadioGroup 源代码的副本并重试。
    【解决方案4】:

    我只是重复使用 RadioGroup 像这样:(请注意 onClick 属性,即单击按钮将触发您的 Activity 的 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>
    

    在您的 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);
                }
            }
        };
    

    并注册它,例如在onCreate():

    @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         this.setContentView(R.layout.scan_settings);
    
         ((RadioGroup) findViewById(R.id.toggleGroup)).setOnCheckedChangeListener(ToggleListener);    
     }
    

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

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

    【讨论】:

    • 我建议在onToggle 中设置新的实际值之前添加((RadioGroup)view.getParent()).check(0);。这将阻止 ToggleButton 的切换功能,并在 ToggleListener 的帮助下强制它像 RadioButton 一样工作。
    • 谢谢...正是我正在寻找的东西,因为我可以在尝试设置样式时摆脱愚蠢的圆形单选按钮圆圈。重要的是要注意,如果您正在为按钮设置样式,请记住有一个 w/ android:state_checked="true" 否则看起来按钮没有做任何事情:-P
    • 在收音机检查监听器中,你应该这样做 if(view.getId == i) { view.setChecked(true) } else { view.setChecked(false); } 那么这样,它就模仿了一个真正的广播组。
    • 我使用这种技术来模拟标签,这样设置标签的样式要容易得多。请注意,如果您在 RadioGroup 内有其他视图(可能出于美观目的?)radioGroup.getChildAt(j) 将与 ClassCastException 崩溃,原因很明显(因为并非所有孩子都会是 ToggleButtons)。只要catch例外,你会没事的。
    • 如果所有这一切的目的只是让一个带有选项样式为复选框的单选组,请在实施之前查看 dhaag23 的答案。当 Android 允许您简单地设置单选选项的样式时,此解决方案正在扭曲 API。
    【解决方案5】:

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

    对于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 文件:

       <?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>
    

    还有我的列表视图:

       <?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> 
    

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

    在 Activity 类中:

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

    【讨论】:

      【解决方案6】:

      这是我设法做到的(不涉及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);
      

      【讨论】:

      • 这几乎是我采用的方法 - 效果很好,易于操作,并且清楚发生了什么。
      【解决方案7】:

      我使用的是 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();
          }
      }
      

      【讨论】:

        【解决方案8】:

        使用任何容器 ViewGroup 添加您的 CompoundButtons(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>
        

        在您的 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;
        

        这里是清除孩子的实用函数。

        /**
         * 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);
                }
            }
        }
        

        【讨论】:

          【解决方案9】:
          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());
                  }
              }
          

          【讨论】:

            【解决方案10】:

            Kotlin 版本:

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

            【讨论】:

              【解决方案11】:

              我正在使用 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>
              

              我没有使用ToggleListener,而是在onCreate() 中听了我拥有的每个ToggleButton:

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

              还有最重要的部分,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
                  }
              }
              

              就是这样。我希望这会有所帮助。

              【讨论】:

              • 工作简单!
              猜你喜欢
              • 1970-01-01
              • 2020-02-06
              • 1970-01-01
              • 1970-01-01
              • 2012-10-16
              • 2014-07-17
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多