此文来自阿钟的投稿,阅读大约15分钟
实现的效果图
动态换肤一般实现的原理
对页面需要换肤的View进行标记
在
Activity#setContentView()
加载view时获取到标记的view(后面会说是要怎么获取到)创建一个Library项目制作我们的皮肤包(res下的资源名称需要与app使用的一致,换肤就是通过使用的资源名称去
皮肤包
里加载相同名字的资源)创建皮肤包对应的
Resources
对象(用于加载皮肤包内的资源)点击换肤将我们标记的View的一些属性上设置的值修改为皮肤包里的值,这样就达到换肤的效果
一、对页面需要换肤的View进行标记
这一步是相对简单的,只要自定义一个属性即可;在获取View的时候判断有无这个属性 有就将这个view存起来
1<?xml version="1.0" encoding="utf-8"?>
2<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 xmlns:skin="http://schemas.android.com/apk/azhon-skin"
4 xmlns:tools="http://schemas.android.com/tools"
5 android:layout_width="match_parent"
6 android:layout_height="match_parent"
7 android:orientation="vertical"
8 android:padding="16dp"
9 tools:context=".MainActivity">
10 <TextView
11 android:layout_width="wrap_content"
12 android:layout_height="wrap_content"
13 android:background="@color/bg_1"
14 android:text="我是一个TextView"
15 android:textColor="@color/title_1"
16 android:textSize="16sp"
17 skin:enable="true" />
18 <Button
19 android:id="@+id/btn_dark"
20 android:layout_width="match_parent"
21 android:layout_height="wrap_content"
22 android:layout_marginTop="20dp"
23 android:background="@color/bg_2"
24 android:text="@string/btn_text"
25 android:textColor="@color/title_2"
26 skin:enable="true" />
27 <Button
28 android:id="@+id/btn_default"
29 android:layout_width="match_parent"
30 android:layout_height="wrap_content"
31 android:layout_marginTop="20dp"
32 android:background="@color/bg_3"
33 android:text="@string/btn_reset_text"
34 android:textColor="@color/title_3" />
35</LinearLayout>
skin:enable="true"
这个就是自定的一个属性取值为
boolean,如果为
true就表示在换肤的时候需要去皮肤包加载对应的资源 ¨K15K **这里使用的是自定义布局加载器
LayoutInflater的
LayoutInflater.Factory2 `来监听View的创建;下面我们来通过阅读源码来具体说一下为什么使用的这个:**
查看AppCompatActivity的setContentView()方法
1public class MainActivity extends AppCompatActivity {
2 @Override
3 protected void onCreate(Bundle savedInstanceState) {
4 super.onCreate(savedInstanceState);
5 setContentView(R.layout.activity_main);
6}
接着继续调用了getDelegate()的setContentView()方法
1// AppCompatActivity.java
2@Override
3public void setContentView(@LayoutRes int layoutResID) {
4 getDelegate().setContentView(layoutResID);
5}
getDelegate()获取到的是AppCompatDelegate这个抽象类的实现类,而他的实现类就只有一个AppCompatDelegateImpl
接着调用了AppCompatDelegateImpl的setContentView()