Android Change Skin, Android Night Mode, 安卓换肤,安卓夜间模式

implementation'com.github.Z-P-J:SkinSwitcher:1.0.1'
框架中的皮肤是以主题的形式存在的,在 values 目录下建立 skins.xml,文件内容如下样例:
<!--定义皮肤的全部属性,例如全局的背景色,全局的字体色等--> <declare-styleable name="skin_attr"> <attr name="main_bg" format="color|reference"></attr> <attr name="button_bg" format="color|reference"></attr> <attr name="button_text_color" format="color|reference"></attr> <attr name="text_color" format="color|reference"></attr> <attr name="line_color" format="color|reference"></attr> </declare-styleable> <!--定义皮肤主题,给皮肤的属性赋值--> <!--白天皮肤--> <style name="AppTheme" parent="android:Theme.Light.NoTitleBar"> <item name="main_bg">@color/main_bg</item> <item name="button_bg">@color/button_bg</item> <item name="button_text_color">@color/button_text_color</item> <item name="text_color">@color/text_color</item> <item name="line_color">@color/line_color</item> </style> <!--夜间皮肤--> <style name="AppNightTheme" parent="android:Theme.Light.NoTitleBar"> <item name="main_bg">@color/night_main_bg</item> <item name="button_bg">@color/night_button_bg</item> <item name="button_text_color">@color/night_button_text_color</item> <item name="text_color">@color/night_text_color</item> <item name="line_color">@color/night_line_color</item> </style> </resources>
如果某个控件需要换肤,则该控件的一些属性的值必须引用皮肤属性,例如:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="?attr/main_bg"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="?attr/text_color" /></LinearLayout>
将 lib 项目的代码引入到自己的项目中。
Application 初始化:
public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); //设置当前皮肤 SkinEngine.getInstance().changeSkin(R.style.AppTheme); }}
Activity 改造:
目的是替换 LayoutInflater 的获取,可以将自己项目的 Activity 统一继承框架的 SkinActivity。如果不能以继承的形式,则需将 SkinActivity 内部的代码拷贝到自己项目相应的类中。
package com.zxy.skin.sdk;import android.content.Context;import android.os.Bundle;import android.support.annotation.Nullable;import android.support.v7.app.AppCompatActivity;import android.view.LayoutInflater;/** * @Description: 使用方可以继承该Activity,或者将内部代码拷贝到自定义的Activity * @author: zhaoxuyang * @Date: 2019/1/31 */public class SkinActivity extends AppCompatActivity { private SkinLayoutInflater mLayoutInfalter; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); getLayoutInflater(); mLayoutInfalter.applyCurrentSkin(); // AppCompatActivity 需要设置 AppCompatDelegate delegate = this.getDelegate(); if (delegate instanceof LayoutInflater.Factory2) { mLayoutInfalter.setFactory2((LayoutInflater.Factory2) delegate); } // 自己的逻辑 } @Override public final LayoutInflater getLayoutInflater() { if (mLayoutInfalter == null) { mLayoutInfalter = new SkinLayoutInflater(this); } return mLayoutInfalter; } @Override public final Object getSystemService(String name) { if (Context.LAYOUT_INFLATER_SERVICE.equals(name)) { return getLayoutInflater(); } return super.getSystemService(name); } @Override protected void onDestroy() { super.onDestroy(); mLayoutInfalter.destory(); }}
类似Activity,Fragment也需要做同样的操作
package com.zxy.skin.sdk;import android.support.v4.app.Fragment;import android.view.LayoutInflater;/** * @Description: 使用方可以继承该Fragment,或者将内部代码拷贝到自定义的Fragment * @author: zhaoxuyang * @Date: 2019/1/31 */public class SkinFragment extends Fragment { @Override public void onDetach() { super.onDetach(); LayoutInflater layoutInflater = getLayoutInflater(); if(layoutInflater instanceof SkinLayoutInflater){ SkinLayoutInflater skinLayoutInflater = (SkinLayoutInflater) layoutInflater; skinLayoutInflater.destory(); } }}
lib 项目中只写了 SkinViewApplicator 和 SkinTextViewApplicator ,支持 background, textColor等属性的换肤操作,其他属性的 Applicator 编写可以参照这两个以及样例中的 SkinCustomViewApplicator。新增的 Applicator 需要注册到框架中。
public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); SkinEngine.changeSkin(R.style.AppTheme); SkinEngine.registerSkinApplicator(CustomView.class, new SkinCustomViewApplicator()); }}
有时候会需要在代码中动态创建view,故也提供了针对动态创建view的方案,使用如下:
public class MyActivity extends SkinActivity { private LinearLayout mLinearLayout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mLinearLayout = new LinearLayout(this); setContentView(mLinearLayout); SkinEngine.setBackgroud(mLinearLayout, R.attr.main_bg); //或者 SkinEngine.applyViewAttr(mLinearLayout, "background", R.attr.main_bg); } @Override protected void onDestroy() { super.onDestroy(); SkinEngine.unRegisterSkinObserver(mLinearLayout); }}
1、Applicator annotation processer