• 面试:换肤方案


    尝试了一下 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小结

  • 相关阅读:
    Android 副屏异显 APP杀进程后未取消问题处理
    java中的interface(接口)
    【电路笔记】-欧姆定律
    华为云HECS安装docker-compose
    【23真题】这套适合考211的同学练手!考察复杂梅森!
    CSDN粉丝福利·全栈思维导图·信年✘原创
    【思维构造】Anonymous Informant—CF1894C
    CSRF(Steam的链接不用随便点)
    【Proteus仿真】Arduino UNO利用74LS148扩展中断
    【滑动窗口】LCR 016. 无重复字符的最长子串
  • 原文地址:https://blog.csdn.net/cpcpcp123/article/details/128128902