自定义属性获取颜色返回无效值

31
我有一个自定义视图,我想设置一个TextView的颜色。
我有
attrs.xml
<declare-styleable name="PropertyView">
    <attr name="propertyTitle" format="string" localization="suggested" />
    <attr name="showTitle" format="boolean" />
    <attr name="propertyTextColor" format="color" />
    <attr name="propertyTextSize" format="dimension" />
</declare-styleable>

我将其设置在布局文件中。

<com.something.views.PropertyView
    android:id="@+id/dwf_rAwayTeamTimePenaltyInput"
    style="@style/mw"
    propertyview:propertyTextSize="16sp"
    propertyview:propertyTitle="@string/AwayTeam"
    propertyview:showTitle="true"
    propertyview:propertyTextColor="@color/textLight" />

而且在我的代码中,我进行了设置

    TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.PropertyView, 0, 0);

    showTitle = a.getBoolean(R.styleable.PropertyView_showTitle, false);
    String title = a.getString(R.styleable.PropertyView_propertyTitle);
    float textSize = a.getDimension(R.styleable.PropertyView_propertyTextSize, -1);
    int color = a.getColor(R.styleable.PropertyView_propertyTextColor, -1);
    textSize = textSize / getResources().getDisplayMetrics().scaledDensity;
    if(BuildConfig.DEBUG) Log.e(getClass().getName(), "Color set to: " + color);

    setShowTitle(showTitle);
    setTitle(title);
    if(textSize >= 0) mTitleTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, textSize);
    if(color != -1) mTitleTextView.setTextColor(color);

    a.recycle();

但颜色仍返回-1。我也尝试将颜色设置为#000,但是这样做会得到一个值为-16777216

我还尝试了a.getInteger和a.getInt

有没有人遇到过这个问题或者有建议?

感谢Alex Fu提供的解决方案

getColor无法处理引用

现在使用以下代码就可以了

ColorStateList color = a.getColorStateList(R.styleable.PropertyView_propertyTextColor);
mTitleTextView.setTextColor(color);
3个回答

23
您在示例中引用了一种颜色,但是根据您的attrs.xml文件,该属性必须是颜色类型,而不是引用。这可能是使用十六进制颜色代码可行而使用引用返回-1的原因。
如果您将格式更改为引用,则还应将检索方法从a.getColor()更改为a.getColorStateList()

你是否更改了attrs.xml中的引用格式?如果是这样,你也更改了a.getColor()方法吗?你应该尝试使用a.getColorStateList()代替。getColorStateList可以理解实色和引用。 - Alex Fu
谢谢,就是这样了 =) 很蠢,getColor不能处理引用,但它可能有一个很好的理由。 - Saren Inden
1
Ps格式应保持为颜色,不是引用,或者可以两者兼备,但对我来说颜色仍然有效,并允许我使用#xxx和@color/xxx。 - Saren Inden
如果属性未设置,它将返回 null。 - Egemen Hamutçu

18

attrs 中存在某种错误。

以下内容完美无缺。


attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <!-- Your View -->
    <declare-styleable name="YourView">
        <attr name="tint_color" format="reference" /> <!-- Important -->
        <attr name="ripple_drawable" format="reference" /> <!-- Important -->
    </declare-styleable>

</resources>

YourView.java

public YourView(Context context) {
    this(context, null);
}

public YourView(Context context, @Nullable AttributeSet attrs) {
    this(context, attrs, 0);
}

public YourView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);

    // Get attrs
    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.YourView, defStyleAttr, 0);

    // Set tint
    int tintStyle = R.styleable.YourView_tint_color;
    if (a.hasValue(tintStyle)) {
        mTintColor = a.getResourceId(tintStyle, 0); // Important
        setTint(mTintColor);
    }

    // Set Ripple
    int rippleStyle = R.styleable.YourView_ripple_drawable;
    if (a.hasValue(rippleStyle)) {
        mRippleDrawable = a.getResourceId(rippleStyle, 0); // Important
        setRipple(mRippleDrawable);
    }

    // End
    a.recycle();
}
用法
<com.your.app.YourView
    ...
    app:ripple_drawable="@drawable/ripple_default"
    app:tint_color="@color/colorWhite" />

9
如果您想让所有类型的颜色生效,
  • 十六进制: #ff0000
  • 颜色资源: @color/primary
  • 颜色选择器: @color/primaryWithStates

您需要将属性定义为颜色和引用两者兼备。

<attr name="propertyTextColor" format="color|reference" />

然后,您只需使用getColorStateList访问该值即可。

val colors = attr.getColorStateList(R.styleable.PropertyView_propertyTextColor)
titleTextView.setTextColor(colors)

对于高级需求,您希望自己处理 ColorStateList

  • 在前两种情况下,您可以使用 colors.defaultColor 访问颜色。
  • 如果您使用了选择器,则必须调用方法 getColorForState

因此,提取颜色的最简单方法是执行以下操作

val currentColor = colors.getColorForState(drawableState, colors.defaultColor)
// do whatever you want with the color

如果当前状态下有颜色,则返回该颜色,否则返回默认颜色。

注意:应将 getColorForState 放置在 drawableStateChanged()方法中,以便在每次状态更改时得到通知。


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