多状态切换按钮

22

我正在开发的应用中,希望有一个多状态的切换按钮(在我的情况下是三个状态),而不是ToggleButton提供的两个状态。我尝试自己创建一个继承Button的类,参考了CompoundButton源码,但实话说阅读它的源代码有点吓人。

有没有一种方法可以使用选择器xml或其他我没有想到的方法来实现一个三态切换按钮?我很迷茫,不知道该怎么做。

5个回答

20

我实现了一个多状态切换按钮,源代码在这里

它的样子是这样的:

enter image description here

而且使用起来非常简单:

<org.honorato.multistatetogglebutton.MultiStateToggleButton
    android:id="@+id/mstb_multi_id"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="10dip"
    mstb:values="@array/planets_array" />

在您的活动中:

MultiStateToggleButton button2 = (MultiStateToggleButton) this.findViewById(R.id.mstb_multi_id);
button2.setOnValueChangedListener(new ToggleButton.OnValueChangedListener() {
    @Override
    public void onValueChanged(int value) {
        Log.d(TAG, "Value: " + value);
    }
});

你是如何像图片中那样自定义它的?在你的文档中没有提到任何自定义。 - Choletski
那是一个旧版本,尝试搜索更早的提交。但基本上你需要修改背景可绘制对象。 - jlhonora
@jlhonora 谢谢你分享这段好代码!我在想是否能够在开关之间进行过渡效果,而不是直接从一个按钮切换到另一个按钮?是否有一种方法可以在它们之间实现过渡效果呢? - amateur programmer
如果我从 Activity A 传递值 Yes 到拥有切换按钮的 Activity B,我该如何将切换按钮的状态设置为选中,以便使用值 Yes - Hoo

14

您可以创建一个自定义的ImageButton来实现这一点,在这种情况下,您需要3个不同的图像。如果需要,您还可以添加更多的状态。

public class FlashButton extends ImageButton {

    public enum FlashEnum {
        AUTOMATIC, ON, OFF
    }

    public interface FlashListener {
        void onAutomatic();
        void onOn();
        void onOff();
    }

    private FlashEnum mState;
    private FlashListener mFlashListener;

    public FlashButton(Context context, AttributeSet attrs) {
        super(context, attrs);

        //Sets initial state
        setState(FlashEnum.AUTOMATIC);
    }


    @Override
    public boolean performClick() {
        super.performClick();
        int next = ((mState.ordinal() + 1) % FlashEnum.values().length);
        setState(FlashEnum.values()[next]);
        performFlashClick();
        return true;
    }


    private void performFlashClick() {
        if(mFlashListener == null)return;
        switch (mState) {
            case AUTOMATIC:
                mFlashListener.onAutomatic();
                break;
            case ON:
                mFlashListener.onOn();
                break;
            case OFF:
                mFlashListener.onOff();
                break;
        }
    }

    private void createDrawableState() {
        switch (mState) {
            case AUTOMATIC:
                setImageResource(R.drawable.ic_flash_auto);
                break;
            case ON:
                setImageResource(R.drawable.ic_flash_on);
                break;
            case OFF:
                setImageResource(R.drawable.ic_flash_off);
                break;
        }
    }


    public FlashEnum getState() {
        return mState;
    }

    public void setState(FlashEnum state) {
        if(state == null)return;
        this.mState = state;
        createDrawableState();

    }

    public FlashListener getFlashListener() {
        return mFlashListener;
    }

    public void setFlashListener(FlashListener flashListener) {
        this.mFlashListener = flashListener;
    }

}

1
你正在让人们变懒 ;) - yajnesh

10

你可以定义一个具有三个条目的选择器作为背景。问题在于,你可以使用哪些按钮属性来使用选择器。你可以有两个布尔值属性,比如A和B,并根据A、B和默认值定义选择器。(A && B将满足A,所以更准确地说它们可以被视为A、!A && B和!A && !B。) 你可以重载现有的属性(例如selected、focused等),或者更优雅地,使用这篇文章中描述的方法定义自己的自定义属性。


看了你提供的线程:我理解步骤1,但是对步骤2有一些疑问。在创建新视图时,扩展View、Button或其他什么更好?除了构造函数和onCreateDrawableState()之外,还有其他方法应该重载吗?如果这些问题很基础,请原谅,这是我第一个真正的应用程序。 - Melde
没事了,已经解决了!谢谢你指导我正确的方向,我很感激。 - Melde
@moonfire 您的代码是专有的吗?我也想创建一个三态切换按钮,并且想看一些其他解决方案以便了解如何实现它。 - JohnMetta
1
@JohnMetta 很抱歉回复晚了,我应该更经常来这里查看。如果你仍需要帮助,我刚刚在[链接](http://goo.gl/WQoGA)上发布了一篇文章。或者,如果你只想下载示例源代码:[链接](http://dl.dropbox.com/u/3448760/AndroidAsILearnIt/CustomButtonExample.zip)。希望能有所帮助! - Melde

7
为什么不使用 RadioGroup 并在内部样式化单选按钮?
 <RadioGroup
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <RadioButton
        android:layout_width="match_parent"
        android:layout_weight="1"
        android:layout_height="wrap_content"
        android:background="@drawable/your_drawable_selector"
        android:button="@android:color/transparent"
        android:gravity="center_horizontal" //center text
        android:text="text"
         />
...

2

Chip 是一个非常好的本地选项。

 <com.google.android.material.chip.ChipGroup
      android:id="@+id/chip_group"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      app:layout_constraintTop_toTopOf="parent"
      app:layout_constraintStart_toStartOf="parent"
      app:singleSelection="true">

      <com.google.android.material.chip.Chip
           android:id="@+id/first_chip"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:gravity="center"
           android:text="Todo"
           android:textAppearance="?android:attr/textAppearance"
           android:textColor="@color/black"
           android:checkable="true"
           style="@style/Widget.MaterialComponents.Chip.Choice"
           app:chipBackgroundColor="@color/colorAccent"/>

           <!-- Second Chip -->
           <!-- Third Chip -->

   </com.google.android.material.chip.ChipGroup>

binding.chipGroup.setOnCheckedChangeListener { chipGroup, i -> 
    when (i) {
        binding.firstChip -> {
            binding.firstChip.setChipBackgroundColorResource(R.color.colorAccent)
        }
        else -> {} 
    }
}
binding.firstChip.isChecked = true  //default

GL

源代码


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