找不到 attr 时如何使自定义视图回退到主题?

How to make a custom view fall back to a theme when attr is not found?

所以我制作了一个自定义视图,可以使用属性对其进行自定义,这很好用。 不过,我现在在为其实施主题系统时遇到了麻烦。我怎样才能取回它?

这就是我初始化 class 的方式:

class PairingCard @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr)

这是我检索的属性:

context.theme.obtainStyledAttributes(
            attrs,
            R.styleable.pairingCard,
            defStyleAttr, R.style.Widget_ScitalysComponents_PairingCard
        ).apply {
            try {
                _strokeColor = getColor(
                    R.styleable.pairingCard_strokeColor,
                    ColorUtils.setAlphaComponent(
                        context.getColorFromAttr(R.attr.colorOnSurface),
                        196
                    )
                )

正如您现在看到的,当它没有找到 attr 设置时,它会回退到具有 196 alpha 的颜色表面。我怎样才能让它恢复到 R.style.Widget_ScitalysComponents_PairingCard 中定义的颜色?

我考虑过再做一次 getColor,但老实说感觉不对。

这是attrs.xml:

<declare-styleable name="pairingCard">
    <attr name="strokeColor" format="color|reference"/>
    <attr name="strokeWidth" format="dimension"/>
    <attr name="cardElevation" format="dimension"/>
    <attr name="collapsedBackgroundColor" format="color"/>
    <attr name="expandedBackgroundColor" format="color"/>
    <attr name="chevronTint" format="color"/>
</declare-styleable>

这是styles.xml:

<style name="Widget.ScitalysComponents.PairingCard" parent="Widget.MaterialComponents.CardView">
    <item name="strokeColor">?attr/colorOnSurface</item>
    <item name="strokeWidth">1dp</item>
    <item name="cardElevation">@dimen/cardview_default_elevation</item>
    <item name="collapsedBackgroundColor">?attr/colorOnSurface</item>
    <item name="expandedBackgroundColor">?attr/colorOnSurface</item>
    <item name="chevronTint">?attr/colorPrimary</item>
</style>

谢谢大家!

在您的 attires.xml 中,您应该定义一个主题引用属性

<declare-styleable name="AppTheme">
     <attr name = "pairingCardStyle" format = "reference"/>
</declare-styleable>

那么你应该在你的样式中定义属性

<style name="Widget.AppTheme.pairingCard" parent="">
     <item name="strokeColor">?attr/colorOnSurface</item>
     .....
</style>

之后,您必须将此样式指向主题中的引用。

<style name="Theme.App" parent="Theme.MaterialComponents.DayNight.NoActionBar">
     <item name = "pairingCardStyle">@style/Widget.AppTheme.pairingCard</item>
     ......
</style>

在您的自定义视图 class 中,您需要定义这些属性

context.theme.obtainStyledAttributes(
        attrs,
        R.styleable.pairingCard,
        R.attr.pairingCardStyle,
        R.style.Widget_AppTheme_pairingCard
    )