当前位置:网站首页>Databinding+LiveData轻松实现无重启换肤
Databinding+LiveData轻松实现无重启换肤
2022-07-28 11:53:00 【塞尔维亚大叔】
作者:ezy
最近项目需要用到无重启动态换肤功能,本来打算用github上star最多的 Android-skin-support
但仔细一看发现太复杂而且2年没维护+大量issues没解决,最终放弃
经过探索,发现 Databinding+LiveData 能低成本实现无重启换肤
- 无重启动态换肤(不需要recreate())
- 无需制作皮肤包
- 无额外依赖(Databinding+LiveData本身几乎开发必备)
- 低侵入性
- AppCompat和Material组件默认支持(少量属性需要额外支持或适配)
- 自定义View/第三方View 适配过程简单(写个绑定适配器就行了)
- 不需要使用 LayoutInflater.Factory
定义皮肤
以下代码定义了三个皮肤Default,Day,Night,通过调用 AppTheme.update(theme) 就可以完成动态换肤
这里皮肤只支持ColorStateList,因为大部分场景只要 ColorStateList 就够了
如果想要,Drawable/String等各种资源都能支持
data class Theme(
val content: Int,
val background: Int,
)
object Themes {
val Default = Theme(Color.RED, Color.GRAY)
val Day = Theme(Color.BLACK, Color.WHITE)
val Night = Theme(Color.MAGENTA, Color.BLACK)
}
object AppTheme {
val background = MutableLiveData<ColorStateList>()
val content = MutableLiveData<ColorStateList>()
init {
update(Themes.Default)
}
fun update(theme: Theme) {
background.value = ColorStateList.valueOf(theme.background)
content.value = ColorStateList.valueOf(theme.content)
}
}
在布局文件中使用皮肤
直接引入AppTheme单例,livedata会关联生命周期,不用担心资源释放
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="ezy.demo.theme.AppTheme" />
</data>
<FrameLayout android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" android:background="#EEEEEE">
<LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" app:background="@{AppTheme.INSTANCE.background}" android:gravity="center" android:orientation="vertical">
<SeekBar android:layout_width="300dp" android:layout_height="wrap_content" android:max="100" android:progress="50" android:progressBackgroundTint="@{AppTheme.INSTANCE.background}" android:progressTint="@{AppTheme.INSTANCE.content}" android:thumb="@android:drawable/ic_btn_speak_now" android:thumbTint="@{AppTheme.INSTANCE.content}" />
<TextView android:layout_width="100dp" android:layout_height="100dp" android:layout_margin="10dp" android:gravity="center" android:text="Hello World!" android:textColor="@{AppTheme.INSTANCE.content}" app:drawableTint="@{AppTheme.INSTANCE.content}" app:drawableTopCompat="@android:drawable/ic_media_pause" />
<LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal">
<TextView android:id="@+id/btn_default" android:layout_width="100dp" android:layout_height="40dp" android:gravity="center" android:text="Default" android:textColor="@{AppTheme.INSTANCE.content}" />
<TextView android:id="@+id/btn_day" android:layout_width="100dp" android:layout_height="40dp" android:gravity="center" android:text="Day" android:textColor="@{AppTheme.INSTANCE.content}" />
<TextView android:id="@+id/btn_night" android:layout_width="100dp" android:layout_height="40dp" android:gravity="center" android:text="Night" android:textColor="@{AppTheme.INSTANCE.content}" />
</LinearLayout>
</LinearLayout>
</FrameLayout>
</layout>
关联生命周期
实际上 Databinding+ObserverableField也能实现无重启换肤,但ObserverableField不能关联生命周期,资源释放麻烦一些
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
// 关联生命周期
binding.lifecycleOwner = this
binding.btnDefault.setOnClickListener {
AppTheme.update(Themes.Default) }
binding.btnDay.setOnClickListener {
AppTheme.update(Themes.Day) }
binding.btnNight.setOnClickListener {
AppTheme.update(Themes.Night) }
}
}
扩展支持的皮肤属性
DataBinding本身已经支持了大量属性,有部分未支持,需要自己实现
实际上就是写个绑定适配器,想要支持第三方控件或自定义控件都差不多,很简单
以下是一些例子
@SuppressLint("RestrictedApi")
@BindingMethods(
BindingMethod(type = ImageView::class, attribute = "tint", method = "setImageTintList")
)
object ThemeAdapter {
@BindingAdapter("background")
@JvmStatic
fun adaptBackground(view: View, value: ColorStateList?) {
view.setBackgroundColor(Color.WHITE)
view.backgroundTintList = value
}
@BindingAdapter("drawableTint")
@JvmStatic
fun adaptDrawableTint(view: TextView, value: ColorStateList?) {
if (view is AppCompatTextView) {
view.supportCompoundDrawablesTintList = value
}
}
@BindingAdapter("android:progressBackgroundTint")
@JvmStatic
fun adaptProgressBackgroundTint(view: SeekBar, value: ColorStateList?) {
view.progressBackgroundTintList = value
}
}
Demo
边栏推荐
- QT signal and slot mechanism (detailed)
- Machine learning practice - logistic regression-19
- 【Base】优化性能到底在优化啥?
- Leetcode remove element & move zero
- 机器学习基础-支持向量机 SVM-17
- 线性分类器(CCF20200901)
- MMA8452Q几种模式的初始化实例
- Flexpro software: measurement data analysis in production, research and development
- Installation and reinstallation of win11 system graphic version tutorial
- Design a thread pool
猜你喜欢

Leetcode94. Middle order traversal of binary trees

连通块&&食物链——(并查集小结)

Summary: golang's ide:vscode usage

Application and download of dart 3D radiative transfer model

03 pyechars rectangular coordinate system chart (example code + effect drawing)

Change the document type in endnode and import it in word

西门子对接Leuze BPS_304i 笔记

Design a thread pool

How can non-standard automation equipment enterprises do well in product quality management with the help of ERP system?

Code layered management of interface testing based on RF framework
随机推荐
SuperMap game engine license module division
LeetCode94. 二叉树的中序遍历
Cloud native - runtime environment
揭秘界面控件DevExpress WinForms为何弃用受关注的MaskBox属性
Introduction to border border attribute
[graduation design] oscilloscope design and Implementation Based on STM32 - single chip microcomputer Internet of things
Machine learning practice - decision tree-22
The openatom openharmony sub forum was successfully held, and ecological and industrial development entered a new journey
BA autoboot plug-in of uniapp application boot
VS code更新后不在原来位置
Redefinition problem of defining int i variable in C for loop
Fundamentals of machine learning - principal component analysis pca-16
Leetcode 1518. wine change
Leetcode206 reverse linked list
Siemens docking Leuze BPS_ 304i notes
How to open the power saving mode of win11 system computer
03 pyechars rectangular coordinate system chart (example code + effect drawing)
leetcode 376. Wiggle Subsequence
Fundamentals of machine learning Bayesian analysis-14
Leetcode: array