Android: 使用选择器更新自定义颜色属性

Android: Updating custom color attribute using selector

我想根据自定义状态定义绘制到 canvas 时应使用的颜色。这是我的进展:

在res/layout/content.xml:

<com.example.package.MyView
    app:primary_color="@drawable/my_selector"
/>

primary_color 是在 res/values/attrs 中定义的自定义属性。xml:

<resource>
    <declare-styleable name="MyView">
        <attr name="primary_color" format="reference"/>
    </declare-styleable>
</resource>

my_selector 定义在 res/drawable/my_selector.xml

<selector xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res/com.example.package">
    <item
        app:state_a="true"
        android:drawable="@drawable/red" />
    <item
        app:state_b="true"
        android:drawable="@drawable/orange" />
    <item
        app:state_c="true"
        android:drawable="@drawable/red" />
</selector>

红橙红定义在res/values/colordrawable.xml:

<resources>
    <drawable name="red">#f00</drawable>
    <drawable name="orange">#fb0</drawable>
    <drawable name="green">#0f0</drawable>
</resources>

在 MyView 中我可以得到这个 drawable:

StateListDrawable primaryColor;

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

    try{

        primaryColor = (StateListDrawable) a.getDrawable(
            R.styleable.MyView_primary_color);
    }finally {
        a.recycle();
    }
}

primaryColor 会随着不同的状态正确更新,我可以通过调用来测试它:

setBackground(primaryColor);

但是我想把这个颜色用在画图上,像这样:

paint.setColor(primaryColor);

但这显然是不允许的。我已经尝试将 primaryColor 转换为具有方法 getColor() 的 ColorDrawable,但如果可能的话,我无法弄清楚该怎么做。

关于如何从选择器中获取可在视图中使用的颜色的任何建议都会很棒。

我发现 ColorStateList 这正是我所需要的。以下是我当前实现的简化版本,以防其他人陷入与我相同的困境。

在res/color/my_selector.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-auto"">

  <item app:state_weak="true" android:color="#F00" />
  <item app:state_average="true" android:color="#0F0" />
  <item app:state_strong="true" android:color="#00F" />
  <item android:color="#FA0" />
</selector>

在 res/layout/content.xml 中(这周围有另一个布局,但这不相关)

<com.example.package.MyView
    android:id="@+id/strMeter"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:primary_color="@color/my_selector"
    />

primary_color 定义为 res/values/attrs 中的引用。xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MyView">
        <attr name="primary_color" format="reference"/>
    </declare-styleable>
</resources>

我在 MyView 的构造函数中获取了对 ColorStateList 的引用:

ColorStateList primaryColor;

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

    try{
        primaryColor = a.getColorStateList(
            R.styleable.MyView_primary_color);
    }finally {
        a.recycle();
    }
}

当我想获取当前状态的颜色时:

int color = secondaryColor.getColorForState(
              getDrawableState(), primaryColor.getDefaultColor());

如果您像我一样实现自定义状态,那么您还必须覆盖 onCreateDrawableState 以使状态实际更新,但有很多 documentation/posts 涵盖了这一点。