Android-Skin-Loader换肤框架剖析

一. 简介

换肤功能,是很多公司项目中的重点功能,仅仅会用那是远远不够的,需要对换肤有全面整体的把握,了解底层实现原理,才能在后面的开发中举一反三,事半功倍。

1. 基本原理

对于Android项目来说,皮肤是什么,皮肤就是UI界面,换皮肤无非就是字体颜色、背景图等这些用户看得见的界面。所以换皮肤最为重要的就是换Android工程下res下面的资源文件,也即如下图所在的资源:
在这里插入图片描述
Google在Android10(API 29)就已经开始支持深色模式,自定义适配方案是使用资源限定符,就像横向布局适配是添加layout-land资源,高密度资源适配是添加drawable-hdpi资源,其自定义深色模式的适配方案则是在res-night下定义一套资源
在这里插入图片描述
在该深色模式资源文件下,所用资源命名和正常资源相同,例如相同的drawable/color/style,那么当系统切换为深色模式时,系统会自动识别并使用res-night下面的资源文件,从而切换为我们想要的深色效果。
换肤功能就类似Google的深色模式,要实现各种换肤功能我们只需要替换对应的资源文件即可,让view布局重新加载新的资源文件。

2. LayoutInflater

首先我们通过上一篇文章了解下 LayoutInflater Factory,通过关于Factory的介绍,我们得出结论:自定义Factory,然后通过setFactory方法设置给系统,那么在系统创建View时则可以进行自定义样式的干预。接下来我们来看看本文研究框架的核心实现原理。

二. 框架Android-Skin-Loader解析

框架 Android-Skin-Loader,官方的版本太旧了,经过改造适配了最新的AndroidX控件以及能正常生成皮肤包,下载地址 Android-Skin-Loader,其工程结构如图
在这里插入图片描述
工程中android-skin-loader-sample是一个使用例子,android-skin-loader-skin是一套皮肤包,android-skin-loader-lib为支持换肤的library,下面我们就来一一介绍了。

1. android-skin-loader-sample使用教程

1.1 xml布局配置

在需要换肤的组件上配置skin:enable=“true”

	<Button
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:background="@drawable/news_item_selector"
        android:textColor="@color/color_sel_skin_btn_text"
        skin:enable="true" />

	<TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@color/news_item_text_color_selector"
        android:textSize="20sp"
        skin:enable="true" />

1.2 Application初始化

public class SkinApplication extends Application {
   
	public void onCreate() {
   
		super.onCreate();
		initSkinLoader();
	}
	private void initSkinLoader() {
   
		SkinManager.getInstance().init(this);
		SkinManager.getInstance().load(); 
	}
}

1.3 Activity继承

Activity继承android-skin-loader-lib中的Base组件

public class MyActivity extends BaseActivity{
   
}

2. android-skin-loader-skin

此module为皮肤包组件,里面是没有任何代码的皮肤资源,用于替换主工程中的资源文件,文件目录如下:

该目录下的资源文件命名需和替换的资源名称保持一样,则才能通过相同的资源名称查到皮肤资源进行替换。
该module为application,可编译出来apk作为皮肤包,可修改后缀名为.skin文件,作为皮肤包放到主工程目录下或者进行网络下载加载。

3. android-skin-loader-lib

换肤的核心逻辑,我们分为三步走:
第一步:加载换肤包到内存中;
第二步:收集所有换肤的View;
第三步:用换肤包中的资源替换View的原有资源。

3.1 SkinManager:加载换肤包

换肤library中最为重要的类是SkinManager,是一个皮肤管理核心类,控制着换肤最为核心的逻辑。在SkinManager类中mResources为引用着换肤包资源的对象,需要换肤的时候从该资源中获取数据,那么该mResources怎么获取到的呢?
Application初始化的时候调用了SkinManager.getInstance().load(),跟进源码

/**
	 * Load resources from apk in asyc task
	 * @param skinPackagePath path of skin apk
	 * @param callback callback to notify user
	 */
	@SuppressLint("StaticFieldLeak")
	public void load(String skinPackagePath, final ILoaderListener callback) {
   
		
		new AsyncTask<String, Void, Resources>() {
   
			@Override
			protected Resources doInBackground(String... params) {
   
				try {
   
					if (params.length == 1) 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值