Android如何正确覆盖主题的自定义视图属性

问题描述

我正在为一个个人应用程序开发一个库,该库可以更轻松地显示自Android顶部向下滑动的自定义吐司。目的是能够在主题中指定不同的样式,以根据应用程序中使用的位置覆盖Toast视图的认样式。

这是我的SimpletoastView类

class SimpletoastView @JvmOverloads constructor(
    context: Context,attrs: AttributeSet? = null
) : LinearLayout(context,attrs) {

init {
    inflate(wrap(context),R.layout.simple_toast_view,this)
}

private val textView: TextView = findViewById(R.id.toast_text)
private val iconView: ImageView = findViewById(R.id.toast_icon)

fun setText(@StringRes stringResId: Int): SimpletoastView {
    textView.setText(stringResId)
    return this
}

fun setIcon(@DrawableRes drawableId: Int,@ColorRes tintColorId: Int = 0): SimpletoastView {
    val drawable = ResourcesCompat.getDrawable(resources,drawableId,context.theme)
    val tintColor = ResourcesCompat.getColor(resources,tintColorId,context.theme)
    iconView.setimageDrawable(drawable)
    iconView.setColorFilter(tintColor)
    return this
}

override fun onLayout(changed: Boolean,l: Int,t: Int,r: Int,b: Int) {
    super.onLayout(changed,l,t,r,b)
    showSlideAnimation()
}

private var animationShowed = false

private fun showSlideAnimation() {
    if (!animationShowed) {
        val height = measuredHeight.toFloat()

        val slideIn = animateTranslationY(from = -height,to = 0f)
        val slideOut = animateTranslationY(from = 0f,to = -height,startDelay = 1500)

        val set = AnimatorSet()
        set.playSequentially(slideIn,slideOut)
        set.start()

        animationShowed = true
    }
}

private fun animateTranslationY(from: Float,to: Float,startDelay: Long = 0): ObjectAnimator {
    return ObjectAnimator.ofFloat(this@SimpletoastView,"translationY",from,to)
        .setDuration(200)
        .also { it.startDelay = startDelay }
}

companion object {
    fun SimpletoastView.showToast() {
        Toast(context)
            .apply {
                this.view = this@showToast
                this.setGravity(Gravity.TOP or Gravity.CENTER_HORIZONTAL,0)
            }
            .show()
    }

    /**
     * Overlays theme with default styles.
     * They will only be used if not already defined in the theme.
     */
    private fun wrap(context: Context): Context {
        return context.apply { theme.applyStyle(R.style.SimpletoastView,false) }
    }
}
}

然后这是布局xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal"
    android:clipChildren="false"
    android:clipToPadding="false"
    android:paddingLeft="16dp"
    android:paddingRight="16dp"
    android:paddingBottom="16dp"
    tools:targetApi="lollipop"
    >

    <FrameLayout
        android:layout_width="300dp"
        android:layout_height="wrap_content"
        android:background="@drawable/sns_shape_rect_corners_8dp"
        android:elevation="3dp"
        android:minHeight="44dp"
        android:paddingLeft="8dp"
        android:paddingRight="8dp"
        >

        <ImageView
            android:id="@+id/toast_icon"
            android:layout_width="44dp"
            android:layout_height="44dp"
            android:scaleType="centerInside"
            android:src="?attr/simpletoastIcon"
            android:tint="?attr/simpletoastIconTint"
            />

        <TextView
            android:id="@+id/toast_text"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="center"
            android:layout_marginLeft="48dp"
            android:layout_marginRight="48dp"
            android:ellipsize="end"
            android:gravity="center"
            android:lines="1"
            android:textColor="#727272"
            android:textSize="14sp"
            tools:text="@tools:sample/lorem/random"
            />

    </FrameLayout>

</FrameLayout>

我创建了以下属性

<declare-styleable name="SimpletoastView">
    <attr name="simpletoastIcon" format="reference" />
    <attr name="simpletoastIconTint" format="reference|color" />
</declare-styleable>

以及以下认样式

<style name="SimpletoastView">
    <item name="simpletoastIconTint">@color/white</item>
    <item name="simpletoastIcon">@null</item>
</style>

一切正常。吐司将显示而没有图标。但是,现在我希望能够允许应用程序主题根据烤面包的调用方式指定样式。

例如,我创建了以下属性

<attr name="chatSentToastStyle" format="reference" />

然后包装类

object SnsChatToast {

@JvmStatic
fun showChatSent(context: Context) {
    val themedContext = context.apply {
        theme.applyStyle(R.attr.chatSentToastStyle,false)
    }

    SimpletoastView(themedContext)
        .setText(R.string.chat_sent1)
        .showToast()
}
}

认样式为

<style name="ChatSentToastStyle" parent="SimpletoastView">
    <item name="simpletoastIconTint">@color/chat_primary</item>
    <item name="simpletoastIcon">@drawable/ic_chat_44dp</item>
</style>

并将以下内容添加主题xml

<style name="Profile.ThemeOverlay" parent="">
    <!-- Profile specific overlay attributes goes here -->
    <item name="chatSentToastStyle">@style/Profile.ChatSentToastStyle</item>

</style>

<style name="Profile.ChatToastStyle" parent="ChatToastStyle">
    <item name="simpletoastIconTint">@color/red</item>
</style>

预期结果是,如果我删除主题替代,那么当我调用showChatSent时,会看到带有聊天图标和聊天原色(绿色)的祝酒词,然后在主题级别我可以指定覆盖样式,在这种情况下,请覆盖颜色并使之变为红色。但是,这些都不起作用。我总是得到认的无图标吐司。我想念什么?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...