简体   繁体   English

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

[英]Android : How to update the selector(StateListDrawable) programmatically

I want to update the selector for a button programmatically. 我想以编程方式更新按钮的选择器。

I can do this with the xml file which is given below 我可以使用下面给出的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>

I want to do the same thing programmatically. 我想以编程方式做同样的事情。 I have tried something like given below 我试过下面给出的东西

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

but it didnt work. 但它没有用。

And how to set android:state_enabled="false" or android:state_enabled="true" programatically. 以及如何以编程方式设置android:state_enabled="false"android:state_enabled="true"

You need to use the negative value of the needed state. 您需要使用所需状态的负值。 Eg: 例如:

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

Notice the "-" sign before android.R.attr.state_enabled . 注意android.R.attr.state_enabled之前的“ - ”符号。

Very late response here but in case anyone else is having problems setting a StateListDrawable programmatically. 这里响应很晚,但是如果其他人在编程时设置StateListDrawable时遇到问题。 Then as with the XML files the order in which you set the states into the StateListDrawable is important. 然后与XML文件一样,将状态设置为StateListDrawable的顺序非常重要。

For example this will work as expected: 例如,这将按预期工作:

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

This won't: 这不会:

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

Not enough rep to comment but the accepted answer did not work for me. 没有足够的回复评论,但接受的答案对我不起作用。

My goal was for designers to set enabled, disabled, and pressed background colors on some button. 我的目标是让设计师在某些按钮上设置启用,禁用和按下的背景颜色。 I intended for them to use it to test colors on different displays. 我打算让他们用它来测试不同显示器上的颜色。

I noticed some other people mentioned it did not work for them either. 我注意到其他一些人提到它也不适用于他们。

The states that need to be defined are 需要定义的状态是

  • not pressed and enabled, this is what you see when the button is enabled and not pressed. 没有按下并启用,这是按钮启用但未按下时看到的内容。
  • pressed and enabled, this is what you see when the button is pressed and enabled 按下并启用,这是按下并启用按钮时看到的内容
  • not enabled. 没有启用。 This is what you see when the button is disabled 这是禁用按钮时看到的内容

Here is some code that will give you an idea of the states. 这里有一些代码可以让你了解状态。 I am using Color.Parse() to generate ints for the colors then I pass them to this method to get the StateListDrawable. 我正在使用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;
}

I am going to answer your question "How to update the selector for a BUTTON programmatically?" 我将回答您的问题“如何以编程方式更新BUTTON的选择器?” by proposing to switch a button for a LinearLayout with embedded ImageView and TextView . 建议使用嵌入式ImageViewTextView切换LinearLayout的按钮。 There are a number of benefits to doing this, especially if you will later decide to customize your views. 这样做有很多好处,特别是如果您稍后决定自定义您的视图。 There is no loss of functionality resulting from this switch. 此切换不会导致功能丢失。 You will still be able to attach same event listeners you can attach to a button, but will be able to avoid the buttons/tabs styling nightmares. 您仍然可以附加可以附加到按钮的相同事件侦听器,但是可以避免按钮/标签样式化噩梦。 Here is a relevant code from the layout.xml 这是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> 

Next, I have a selector file called custom_image.xml located in the drawable folder. 接下来,我有一个名为custom_image.xml的选择器文件位于drawable文件夹中。 Here is the content of the selector file 这是选择器文件的内容

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

The three source image files (disabled_img.png, unselected_img.png, selected_img.png) are also located in the drawable folder. 三个源图像文件(disabled_img.png,unselected_img.png,selected_img.png)也位于drawable文件夹中。

Now back to your Java code. 现在回到您的Java代码。 There is no need for the funky StateListDrawable garbage for many reasons. 出于多种原因,不需要时髦的StateListDrawable垃圾。 First, it just looks ugly, and is hard to maintain. 首先,它看起来很丑陋,很难维护。 But most importantly it goes against the principles of keeping your logic separate from your presentation. 但最重要的是,它违背了将逻辑与演示文稿分开的原则。 If you are managing your drawable resources in Java code, you know you are doing something fundametally wrong. 如果您使用Java代码管理可绘制资源,那么您知道自己正在做一些基本错误的事情。

Here is what I am proposing instead. 这是我提出的建议。 Whenever you want your button to be selected, you just pop this one-liner in there: 每当你想要选择你的按钮时,你只需在那里弹出这个单行:

((LinearLayout)findViewById(R.id.button)).setSelected(true);

Or whenever you want the button to be in the disabled state, here is another one-liner: 或者,当您希望按钮处于禁用状态时,这是另一个单行:

((ImageView)findViewById(R.id.background)).setEnabled(false);

Please notice that in this last example I am specifying the disabled state on the ImageView inside the LinearLayout. 请注意,在最后一个示例中,我在LinearLayout内的ImageView上指定了禁用状态。 For some reason whenever you change the enabled / disabled state of the LinearLayout, the selector is not being triggered. 由于某种原因,每当您更改LinearLayout的启用/禁用状态时,都不会触发选择器。 It works fine when you do it on the ImageView instead. 相反,它在ImageView上运行时效果很好。

I don't know how you are adding the StateListDrawable , since the code is not here. 我不知道你是如何添加StateListDrawable ,因为代码不在这里。 But be sure to be check the documentation and the adding the setState() . 但一定要检查文档并添加setState()

You can set the properties from the View, such as yourView.setEnabled(true) 您可以从View中设置属性,例如yourView.setEnabled(true)

I hope that helps 我希望有所帮助

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM