当前位置:网站首页>Databinding+livedata can easily realize skin changing without restart
Databinding+livedata can easily realize skin changing without restart
2022-07-28 13:03:00 【Serbian uncle】
author :ezy
Recent projects need to use the dynamic skin changing function without restart , I was going to use github On star The most Android-skin-support
But a closer look shows that it's too complicated and 2 No maintenance in + A lot of issues It's not solved , Finally give up
After exploration , Find out Databinding+LiveData It can realize skin change without restart at low cost
- Dynamic skin changing without restart ( Unwanted recreate())
- No need to make a skin bag
- No extra dependence (Databinding+LiveData It is almost necessary to develop itself )
- Low invasive
- AppCompat and Material Default component support ( A small number of attributes require additional support or adaptation )
- Customize View/ The third party View The adaptation process is simple ( Just write a binding adapter )
- No need to use LayoutInflater.Factory
Define skin
The following code defines three skins Default,Day,Night, By calling AppTheme.update(theme) You can complete the dynamic skin change
The skin here only supports ColorStateList, Because most scenes just ColorStateList That's enough
If you want to ,Drawable/String And other resources can support
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)
}
}
Use skins in layout files
Directly introducing AppTheme Single case ,livedata Will be associated with the lifecycle , Don't worry about resource release
<?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>
Associated lifecycle
actually Databinding+ObserverableField It can also realize skin change without restart , but ObserverableField Cannot associate lifecycle , Resource release is more troublesome
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
// Associated lifecycle
binding.lifecycleOwner = this
binding.btnDefault.setOnClickListener {
AppTheme.update(Themes.Default) }
binding.btnDay.setOnClickListener {
AppTheme.update(Themes.Day) }
binding.btnNight.setOnClickListener {
AppTheme.update(Themes.Night) }
}
}
Extend supported skin properties
DataBinding It already supports a large number of properties , Some are not supported , You have to implement it yourself
Actually, it's just writing Binder Adapter , It's almost the same to support third-party controls or custom controls , It's simple
Here are some examples
@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
边栏推荐
- Sliding Window
- Can molecular modeling solve the data dilemma of AI pharmacy?
- LeetCode394 字符串解码
- Low code: reduce technical capability requirements and improve software development efficiency
- Understanding of vite2
- What if win11 cannot recognize Ethernet
- Sliding Window
- Black cat takes you to learn EMMC protocol chapter 27: what is EMMC's dynamic capacity?
- Science 重磅:AI设计蛋白质再获突破,可设计特定功能性蛋白质
- 企业数字化本质
猜你喜欢

【C语言易错点】第4篇:结构体在内存中存储规则详讲

Machine learning practice - integrated learning-23

机器学习实战-集成学习-23

What if the win11 folder cannot be opened

Machine learning Basics - decision tree-12

Black cat takes you to learn EMMC Protocol Part 24: detailed explanation of EMMC bus test program (cmd19 & cmd14)

Redefinition problem of defining int i variable in C for loop

Leetcode:704 binary search

Leetcode 42. rainwater connection

【嵌入式C基础】第4篇:运算符的使用
随机推荐
线性分类器(CCF20200901)
Leetcode: array
Linear classifier (ccf20200901)
Shenwenbo, researcher of the Hundred Talents Program of Zhejiang University: kernel security in the container scenario
黑猫带你学UFS协议第2篇:UFS相关名词释义
【C语言易错点】第4篇:结构体在内存中存储规则详讲
[July 5 event preview] Flink Summit
LeetCode每日一题(2196. Create Binary Tree From Descriptions)
Force buckle 315 calculates the number of elements smaller than the current element on the right
机器学习基础-主成分分析PCA-16
LeetCode 42.接雨水
Leetcode:704 binary search
BA autoboot plug-in of uniapp application boot
[embedded explanation] key scanning based on finite state machine and stm32
Cloud native - runtime environment
[basic teaching of Bi design] detailed explanation of OLED screen use - single chip microcomputer Internet of things
机器学习实战-集成学习-23
Quick read in
Machine learning practice - decision tree-22
How can non-standard automation equipment enterprises do well in product quality management with the help of ERP system?