如何添加自定义按钮状态 [英] How to add a custom button state

查看:100
本文介绍了如何添加自定义按钮状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

例如,默认按钮在其状态和背景图片之间具有以下依赖关系:

For instance, the default button has the following dependencies between its states and background images:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_window_focused="false" android:state_enabled="true"
        android:drawable="@drawable/btn_default_normal" />
    <item android:state_window_focused="false" android:state_enabled="false"
        android:drawable="@drawable/btn_default_normal_disable" />
    <item android:state_pressed="true" 
        android:drawable="@drawable/btn_default_pressed" />
    <item android:state_focused="true" android:state_enabled="true"
        android:drawable="@drawable/btn_default_selected" />
    <item android:state_enabled="true"
        android:drawable="@drawable/btn_default_normal" />
    <item android:state_focused="true"
        android:drawable="@drawable/btn_default_normal_disable_focused" />
    <item
        android:drawable="@drawable/btn_default_normal_disable" />
</selector>

如何定义自己的自定义状态(类似于android:state_custom),然后才能使用它动态更改按钮的外观?

How can I define my own custom state (smth like android:state_custom), so then I could use it to dynamically change my button visual appearance?

推荐答案

@(Ted Hopp)表示的解决方案有效,但需要进行一些更正:在选择器中,项目状态需要一个"app:"前缀,否则充气机将无法正确识别名称空间,并且将以静默方式失败;至少这是我身上发生的事情.

The solution indicated by @(Ted Hopp) works, but needs a little correction: in the selector, the item states need an "app:" prefix, otherwise the inflater won't recognise the namespace correctly, and will fail silently; at least this is what happens to me.

允许我在此处报告整个解决方案,以及更多详细信息:

Allow me to report here the whole solution, with some more details:

首先,创建文件"res/values/attrs.xml":

First, create file "res/values/attrs.xml":

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="food">
        <attr name="state_fried" format="boolean" />
        <attr name="state_baked" format="boolean" />
    </declare-styleable>
</resources>

然后定义您的自定义类.例如,它可以是派生自"Button"类的"FoodButton"类.您将必须实现一个构造函数.实现这一功能,这似乎是充气机使用的功能:

Then define your custom class. For instance, it may be a class "FoodButton", derived from class "Button". You will have to implement a constructor; implement this one, which seems to be the one used by the inflater:

public FoodButton(Context context, AttributeSet attrs) {
    super(context, attrs);
}

在派生类之上:

private static final int[] STATE_FRIED = {R.attr.state_fried};
private static final int[] STATE_BAKED = {R.attr.state_baked};

此外,您的状态变量:

private boolean mIsFried = false;
private boolean mIsBaked = false;

还有几个二传手:

public void setFried(boolean isFried) {mIsFried = isFried;}
public void setBaked(boolean isBaked) {mIsBaked = isBaked;}

然后覆盖函数"onCreateDrawableState":

Then override function "onCreateDrawableState":

@Override
protected int[] onCreateDrawableState(int extraSpace) {
    final int[] drawableState = super.onCreateDrawableState(extraSpace + 2);
    if (mIsFried) {
        mergeDrawableStates(drawableState, STATE_FRIED);
    }
    if (mIsBaked) {
        mergeDrawableStates(drawableState, STATE_BAKED);
    }
    return drawableState;
}

最后,这个难题最微妙的部分;定义StateListDrawable的选择器,它将用作窗口小部件的背景.这是文件"res/drawable/food_button.xml":

Finally, the most delicate piece of this puzzle; the selector defining the StateListDrawable that you will use as a background for your widget. This is file "res/drawable/food_button.xml":

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res/com.mydomain.mypackage">
<item
    app:state_baked="true"
    app:state_fried="false"
    android:drawable="@drawable/item_baked" />
<item
    app:state_baked="false"
    app:state_fried="true"
    android:drawable="@drawable/item_fried" />
<item
    app:state_baked="true"
    app:state_fried="true"
    android:drawable="@drawable/item_overcooked" />
<item
    app:state_baked="false"
    app:state_fried="false"
    android:drawable="@drawable/item_raw" />
</selector>

请注意"app:"前缀,而在标准android状态下,您将使用前缀"android:". XML名称空间对于充气机的正确解释至关重要,它取决于您要在其中添加属性的项目的类型.如果是应用程序,请将 com.mydomain.mypackage 替换为应用程序的实际程序包名称(不包括应用程序名称).如果它是一个库,则必须使用"http://schemas.android.com/apk/res-auto"(并使用Tools R17或更高版本),否则会出现运行时错误.

Notice the "app:" prefix, whereas with standard android states you would have used prefix "android:". The XML namespace is crucial for a correct interpretation by the inflater and depends on the type of project in which you are adding attributes. If it is an application, replace com.mydomain.mypackage with the actual package name of your application (application name excluded). If it is a library you must use "http://schemas.android.com/apk/res-auto" (and be using Tools R17 or later) or you will get runtime errors.

一些注意事项:

  • 看来您不需要调用"refreshDrawableState"函数,至少就我而言,该解决方案可以按原样工作

  • It seems you don't need to call the "refreshDrawableState" function, at least the solution works well as is, in my case

为了在布局xml文件中使用自定义类,您将必须指定完全限定的名称(例如com.mydomain.mypackage.FoodButton)

In order to use your custom class in a layout xml file, you will have to specify the fully qualified name (e.g. com.mydomain.mypackage.FoodButton)

您可以将自定义状态设置为标准状态(例如android:pressed,android:enabled,android:selected),以表示更复杂的状态组合

You can as weel mix-up standard states (e.g. android:pressed, android:enabled, android:selected) with custom states, in order to represent more complicated state combinations

这篇关于如何添加自定义按钮状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆