Android换肤方案总结

作者: zizi192 | 来源:发表于2018-07-23 12:15 被阅读136次

这篇总结也是拖了很久了,欠下的技术债必须得偿还啦~

Android换肤在使用场景上可以区分为静态换肤/动态换肤、应用内换肤/插件式换肤。不同的换肤方案,适用于不同的业务场景。

setTheme可以较好的支持静态换肤,但如果要动态换肤则需要解决的核心问题有:

  • 外部资源的加载
  • 定位到需要换肤的View

第一个资源加载的问题可以通过构造AssetManager,反射调用其addAssetPath就可以完成。
第二个问题,就可以利用在onCreateView中,根据view的属性来定位。应用内换肤一般以资源前缀或后缀来区分不同资源,辅助以tag或侵入式等来区分换肤的view;进而保存需要换肤的view引用。

在个人的应用场景中,需要支持动态实时换肤,且以应用内换肤为主。最终在开源框架ChangeSkin的基础上进行了改造来满足需求。

下面会介绍不同的换肤方案及优缺点。

切换Theme

首先,在attr.xml中定义支持换肤的属性。一般是textColor,background等。如果系统支持的字体颜色,背景色较多,则需要增加很多的自定义属性。

<resources>
    <attr name="textColor" format="reference|color"/>
    <attr name="background" format="reference|color"/>
</resources>

其次,在不同主题的style中定义属性值。

<style name="AppTheme_Light" >
    <item name="textColor">@android:color/black</ item>
    <item name="android:background">@android:color/white</ item>
</style>
 
<style name="AppTheme_Night">
    <item name="textColor">@android:color/white</ item>
    <item name="android:background">@android:color/black</ item>
</style>

再次,View上应用style(?attr/nbackground表示使用style内的此属性作为view 的background).

<TextView
    android :id="@+id/textview"
    android :layout_width="wrap_content"
    android :layout_height="wrap_content"
    android :text="Hello World!"
    android :background="?attr/background"
    android :textColor="?attr/textColor"/>

最后,在Java代码内根据情况设置主题并刷新界面。如果要支持动态换肤,则必须要设置换肤的监听,全部页面实现一个回调。原因是setTheme方法要在setContentView之前调用才能生效。

//设置换肤回调
@Override
protected void onSkinChange() {
    TypedValue background = new TypedValue();
    TypedValue textColor = new TypedValue();
    Resources.Theme theme = getTheme();
    theme.resolveAttribute(R.attr.background, background, true);
    theme.resolveAttribute(R.attr.textColor, textColor, true);
    mTextView .setTextColor(textColor.data);
    mTextView.setBackgroundResource(background.resourceId);
    
    ...
}

方案优点:

  • 非侵入式,兼容性好,接口完善。

方案缺点:

  • 为了支持动态换肤,需要recreate页面或遍历view来实现。有性能消耗。
  • 如果应用设计无颜色规范,导致应用内颜色等定义较多,则需要定义较多自定义属性。

换肤框架AndroidChangeSkin

项目地址:https://github.com/hongyangAndroid/AndroidChangeSkin
该框架通过相同名称+不同皮肤后缀来区分不同皮肤,再通过View的Tag来标志夜间模式的Drawable/Color引用。
如实现黑白皮肤,文本颜色item_text_color有一套默认皮肤,一套黑色皮肤定义资源item_text_color,item_text_color_black。
方案优点:

  • 非侵入式, Android支持度高
  • 支持应用内换肤和插件换肤
  • 目前支持src,background,textColor,支持扩展

方案缺点:

  • 需要自定义Tag;部分View的Tag被其他逻辑占用
  • 使用方式繁琐
<TextView
    android :layout_width="wrap_content"
    android :layout_height="wrap_content"
    android :tag="skin:item_text_color:textColor"
    android :text="@string/hello_world"
    android :textColor="@color/item_text_color"/>

换肤框架ChangeSkin

项目地址:https://github.com/hongyangAndroid/ChangeSkin.
针对框架AndroidChangeSkin需要为每个支持换肤的view设置tag,鸿洋实现了侵入式换肤的方案。该框架也参考了AndroidSkinLoader。
该框架最主要的方法在于baseSkinactivity中,侵入了onCreateView方法,使用了视图兼容工厂。遍历反射创建的view,根据资源前缀来标志是否支持换肤,存储支持换肤的view引用,以实现动态换肤。

在应用的某些场景,需要动态获取当前皮肤某资源信息,如黑白皮肤的主题颜色,需要通过SkinManager获取ResourceManager对象,进而通过Resources的getColor方法获取颜色值。参数为资源名,为了便于开发,可通过getResourceName将resId转化为resName。

public static int getSkinColor(@ColorRes int resId){
        if (SkinManager.getInstance().isUseSkinPlugin()) {
            String resName = CoreApplication.getInstance().getResources().getResourceName(resId);
            return SkinManager.getInstance().getResourceManager().getColor(resName);
        }

        int retColor = CoreApplication.getInstance().getResources().getColor(resId);
        return retColor;
    }

方案优点:

  • 使用方便,对开发者无额外成本
  • 支持应用内换肤和插件换肤
  • 目前支持src,background,textColor,支持扩展

方案缺点:

  • 侵入式换肤,可能存在兼容性问题

换肤框架AndroidSkinLoader

该方案为侵入式方案,通过为LayoutInfalter去设置自定义Factory,对加载的View进行分析和提取。

具体可参考项目地址:https://github.com/fengjundev/Android-Skin-Loader

参考文章:
android 换肤(1)——插件式无缝换肤(解析鸿洋大神的换肤流程)
android 换肤(2)——插件式无缝换肤(解析鸿洋大神的换肤流程)
Android换肤技术总结
Android夜间模式调研总结

相关文章

  • android 夜间模式(换肤)总结

    一、android 平台常见的换肤方案. Android 平台常见的额换肤方式总结起来有如下三种: 1.设置set...

  • Android换肤方案总结

    这篇总结也是拖了很久了,欠下的技术债必须得偿还啦~ Android换肤在使用场景上可以区分为静态换肤/动态换肤、应...

  • 夜间模式实践

    现状 夜间模式是android换肤的一种,关于换肤的相关知识总结,大家可以参考这篇文章Android换肤技术总结-...

  • Android Runtime Resource Overlay

    系统换肤方案来源于2014年sony在Android 5.0上针对定制化的Theme所提供的换肤方案,并且该方案被...

  • Android换肤方案

    换肤方案:(1)内部资源加载方案:定义几套主题,所有的图片,背景等资源都打包到apk里面,通过BaseActivi...

  • Android换肤方案

    没有任何侵入型的一行代码实现动态换肤的android换肤组件 欢迎star https://github.com/...

  • Android换肤

      目前比较流行的几种换肤方案是基于开源框架Android-skin-support、Android-Skin-L...

  • Android 在线换肤方案总结分享

    文章首发于imesong的个人网站 本文主要是在公司内部的一次分享会内容,基于 Android-Skin-Load...

  • Android 应用换肤方案的总结

    虽然现在已经有很多不错的换肤方案,但是这些方案或多或少都存在自己的问题。在这篇文章中,我将对 Android 现有...

  • Android换肤机制

    参考资料: Android换肤技术总结 Android应用程序插件化研究之AssetManager Android...

网友评论

    本文标题:Android换肤方案总结

    本文链接:https://www.haomeiwen.com/subject/otpdmftx.html