Android 动态换肤 MXSKinChange

2021-08-20  本文已影响0人  仙大

MXSkinChange 动态换肤插件

项目源码:https://gitee.com/zhangmengxiong/MXSkinChange

Gradle引用:

    implementation 'com.gitee.zhangmengxiong:MXSkinChange:1.0.6'

插件深度绑定 AppCompatActivity Lifecycle,Activity打开和结束自动释放对View的引用
项目原理:
使用 LayoutInflaterCompat.setFactory2(layoutInflater, factory) 方法,对Activity创建View的过程进行注入,对系统View/ViewGroup替换为自定义View/ViewGroup,自定义View会对相关的资源引用进行资源名替换引用

用法

1:Application 中需要初始化一次

MXSkinManager.init(this)

2:在Activity中绑定Factory

override fun onCreate(savedInstanceState: Bundle?) {
    MXSkinManager.attach(lifecycle, layoutInflater)
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
}

3:定义新皮肤资源文件

这里假设皮肤名称:dark

android {
    sourceSets {
        main {
            res.srcDirs = ['src/main/res', 'src/main/res-dark']
        }
    }
}
// 加载新皮肤 :dark
MXSkinManager.loadSkin("dark")

// 恢复默认皮肤:
MXSkinManager.resetSkin()

如何适配自定义View

插件并不能识别自定义的View,需要手动注入或继承自相对应的View

如何自定义一个继承自系统View的自定义View

示例:自定义一个继承自LinearLayout的View,只需要继承自 MXSkinLinearLayout 就可以

class ColorLinearLayout @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null
) : MXSkinLinearLayout(context, attrs) {
    init {
        LayoutInflater.from(context).inflate(R.layout.layout_color, this, true)
    }
    
    *****
    
    // 返回TRUE时,皮肤变更时会刷新这个View的相关资源引用
    override fun needObserved(): Boolean  = true
}

类似 MXSkinLinearLayout 的View还有:

如何自定义一个第三方View

class CView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null
) : androidx.appcompat.widget.AppCompatTextView(context, attrs), ISkinView {
    private var colorResId = BaseAttr.INVALID_ID

    init {
        val a: TypedArray = context.obtainStyledAttributes(
            attrs,
            R.styleable.CView,
            0, 0
        )
        try {
            colorResId = BaseAttr.getResourceId(a, R.styleable.CView_color)
        } finally {
            a.recycle()
        }

        onSkinChange()
    }

    override fun getName(): String {
        // 这里返回这个View在xml中定义的名字
        return CView::class.java.name
    }

    override fun getSelfView(): View {
        return this
    }

    override fun onSkinChange() {
        // 皮肤更新
        if (colorResId != BaseAttr.INVALID_ID) {
            val color = MXSkinResource.getColorStateList(context, colorResId)
            setTextColor(color)
        }
    }
}
MXSkinViewRegister.register(CView::class.java)
上一篇下一篇

猜你喜欢

热点阅读