• 面试:换肤方案


    尝试了一下 3 个换肤方案,Demo 送上

    方案一:使用主题文件

    主题中定义具体的资源style,我们需要在setContentView之前设置我们的主题即可。

    1. override fun onCreate(savedInstanceState: Bundle?) {
    2. super.onCreate(savedInstanceState)
    3. if ("default" != getSp(this, "theme")) {
    4. setTheme(R.style.Theme_Style1)
    5. }
    6. setContentView(R.layout.activity_demo1_theme)
    7. }

    缺点:需要重新创建Activity才会生效,会导致界面状态丢失

    方案二:LayoutInflater#setFactory2

    既然使用setTheme方案都需要重新创建Activity,那么其实我们也可以自己找到所有需要换肤的控件,然后手动设置就可以完成换肤了,这种方案代表框架Android-Skin-Loader,不过可惜很久没有更新了。

    大致步骤如下:

    1、收集需要换肤的控件以及属性

    2、制作皮肤包

    3、读取皮肤包

    4、动态刷新控件

    5、其他:支持手动设置属性,手动添加控件

    其实我们查看LayoutInflater#createViewFromTag源码即可知道,系统在创建View之前会使用LayoutInflater#tryCreateView去看看外部是不是想自己创建控件,具体会调用外部设置的Factory2#onCreateView,如果返回null,则系统去创建,那么我们就可以在这个里面解析对应控件的属性,如果是支持换肤的属性,则创建自己手动控件,并保存。

    方案特点:

    1、自动化程度比较高,改造成本也低。

    2、存在一定侵入性。

    方案三:使用tag标记需要换肤的属性

    此方案其实与方案二的步骤非常相似,唯一不同的地方在于,方案二使用了layoutFactory去获取所有支持换肤的控件,本方案则是在控件上设置tag的方式来标记,方案二在创建布局的时候收集所有控件,性能上存在部分损耗,使用tag则是在换肤的时候,遍历控件树去修改属性。代表方案为AndroidChangeSkin。https://github.com/hongyangAndroid/AndroidChangeSkin

    在xml中使用tag。

    1. <Button
    2. android:layout_width="match_parent"
    3. android:layout_height="50dp"
    4. android:layout_marginTop="10dp"
    5. android:background="#ffffff"
    6. android:gravity="center"
    7. android:tag="text=string/test_string|textColor=color/skin_test_color"
    8. android:text="@string/test_string"
    9. android:textColor="?attr/module_color" />

    换肤的时候遍历视图树。

    然后就是与方案二中一样,读取皮肤包资源咯。

    方案特点:侵入性较低,但是使用、改造成本比较高。

    相关原理参考:

    换肤、全局字体替换、无需编写shape、selector 的原理Factory小结

  • 相关阅读:
    SpringBoot整合minio分布式文件实操
    线程并发安全问题解决方案
    #820 Div.3 G. Cut Substrings dp*
    特殊的类——集合与泛型(C#)
    电容式雨雪传感器
    智能DNA分子纳米机器人模型来了
    oracle11g-图形安装(centos7)
    腾讯云~docker onlyoffice7.1.1 word excel ppt在线编辑、在线预览_部署01
    【K8S系列】第九讲:Kubernetes 之探针
    工作好多年,回忆人生--高中三年
  • 原文地址:https://blog.csdn.net/cpcpcp123/article/details/128128902