Android:如何以编程方式更新选择器(StateListDrawable)

Man*_*ani 60 android state button

我想以编程方式更新按钮的选择器.

我可以使用下面给出的xml文件来完成此操作

<?xml version="1.0" encoding="UTF-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
   <item android:state_enabled="false"
         android:drawable="@drawable/btn_off" />
   <item android:state_pressed="true"
         android:state_enabled="true" 
         android:drawable="@drawable/btn_off" />
   <item android:state_focused="true"
         android:state_enabled="true" 
         android:drawable="@drawable/btn_on" />
   <item android:state_enabled="true" 
         android:drawable="@drawable/btn_on" />
</selector>
Run Code Online (Sandbox Code Playgroud)

我想以编程方式做同样的事情.我试过下面给出的东西

private StateListDrawable setImageButtonState(int index)
{
    StateListDrawable states = new StateListDrawable();

    states.addState(new int[] {android.R.attr.stateNotNeeded},R.drawable.btn_off); 
    states.addState(new int[] {android.R.attr.state_pressed, android.R.attr.state_enabled},R.drawable.btn_off);
    states.addState(new int[] {android.R.attr.state_focused, android.R.attr.state_enabled},R.drawable.btn_on);
    states.addState(new int[] {android.R.attr.state_enabled},R.drawable.btn_on);

    return states;
}
Run Code Online (Sandbox Code Playgroud)

但它没有用.

以及如何设置android:state_enabled="false"android:state_enabled="true"编程.

Osi*_*Osi 114

您需要使用所需状态的负值.例如:

states.addState(new int[] {-android.R.attr.state_enabled},R.drawable.btn_disabled);
Run Code Online (Sandbox Code Playgroud)

注意之前的" - "符号android.R.attr.state_enabled.

  • @ing0 所以它是为了状态的“假”值?我认为这是一个糟糕的 API 选择,因为它不直观,再加上如果有一天它会超过 2 个值(真和假)……无论如何,谢谢。 (2认同)

小智 8

这里响应很晚,但是如果其他人在编程时设置StateListDrawable时遇到问题.然后与XML文件一样,将状态设置为StateListDrawable的顺序非常重要.

例如,这将按预期工作:

StateListDrawable sld = new StateListDrawable();
sld.addState(new int[] { android.R.attr.state_pressed }, new ColorDrawable(Color.GRAY));
sld.addState(new int[] {}, new ColorDrawable(Color.GREEN));
Run Code Online (Sandbox Code Playgroud)

这不会:

StateListDrawable sld = new StateListDrawable();
sld.addState(new int[] {}, new ColorDrawable(Color.GREEN));
sld.addState(new int[] { android.R.attr.state_pressed }, new ColorDrawable(Color.GRAY));
Run Code Online (Sandbox Code Playgroud)

  • 似乎需要将默认状态设置为 LAST。这没有任何意义,但这样做确实让它起作用了......*smh*...... (2认同)

Vos*_*ski 6

没有足够的回复评论,但接受的答案对我不起作用.

我的目标是让设计师在某个按钮上设置启用,禁用和按下的背景颜色.我打算让他们用它来测试不同显示器上的颜色.

我注意到其他一些人提到它也不适用于他们.

需要定义的状态是

  • 没有按下并启用,这是按钮启用但未按下时看到的内容.
  • 按下并启用,这是按下并启用按钮时看到的内容
  • 没有启用.这是禁用按钮时看到的内容

这里有一些代码可以让你了解状态.我正在使用Color.Parse()为颜色生成int,然后我将它们传递给此方法以获取StateListDrawable.

private StateListDrawable createDrawable(int enabled, int pressed, int disabled) {
  StateListDrawable stateListDrawable = new StateListDrawable();

  stateListDrawable.addState(new int[] { -android.R.attr.state_pressed, android.R.attr.state_enabled }, new ColorDrawable(enabled));
  stateListDrawable.addState(new int[] { android.R.attr.state_pressed, android.R.attr.state_enabled }, new ColorDrawable(pressed));
  stateListDrawable.addState(new int[] { -android.R.attr.state_enabled }, new ColorDrawable(disabled));

  return stateListDrawable;
}
Run Code Online (Sandbox Code Playgroud)


Tem*_*age 5

我将回答您的问题“如何以编程方式更新按钮的选择器?” 通过建议切换一个LinearLayout带有嵌入式ImageView和的按钮TextView。这样做有很多好处,尤其是如果您稍后决定自定义视图时。此开关不会造成功能损失。您仍然可以附加可以附加到按钮的相同事件侦听器,但是可以避免将按钮/标签设置为噩梦。这是来自layout.xml的相关代码

    <LinearLayout 
        android:id="@+id/button"
        style="@style/ButtonStyle">
        <ImageView 
            android:id="@+id/background"
            android:src="@drawable/custom_image"/>
        <TextView 
            style="@style/TextStyle"
            android:text="Custom Button"
            android:id="@+id/text"/>
    </LinearLayout> 
Run Code Online (Sandbox Code Playgroud)

接下来,我在drawable文件夹中有一个名为custom_image.xml的选择器文件。这是选择器文件的内容

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/disabled_img"     android:state_enabled="false" />
    <item android:drawable="@drawable/unselected_img"     android:state_selected="false" />
    <item android:drawable="@drawable/selected_img"     android:state_selected="true" />
</selector>
Run Code Online (Sandbox Code Playgroud)

三个源图像文件(disabled_img.png,unselected_img.png,selected_img.png)也位于可绘制文件夹中。

现在回到您的Java代码。StateListDrawable由于多种原因,不需要时髦的垃圾。首先,它看起来很难看,很难维护。但最重要的是,它违反了使逻辑与演示分离的原则。如果您正在用Java代码管理可绘制资源,那么您就知道自己在做一些根本性的错误。

这是我的建议。每当您希望选择按钮时,只要在其中弹出此单线即可:

((LinearLayout)findViewById(R.id.button)).setSelected(true);
Run Code Online (Sandbox Code Playgroud)

或者,每当您希望按钮处于禁用状态时,这都是另一种形式:

((ImageView)findViewById(R.id.background)).setEnabled(false);
Run Code Online (Sandbox Code Playgroud)

请注意,在最后一个示例中,我在LinearLayout中的ImageView上指定了禁用状态。由于某些原因,无论何时更改LinearLayout的启用/禁用状态,都不会触发选择器。当您在ImageView上执行此操作时,它可以正常工作。