2 Star 1 Fork 2

冰雪情缘TV / OpenDemo

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
SkinManager.java 9.69 KB
一键复制 编辑 原始数据 按行查看 历史
package com.open.demo.skin;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.Button;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.core.content.ContextCompat;
import com.open.demo.R;
/**
* <pre>
* 1.加载本地的 style.
* 2.添加(addSkin)到主题管理器(SkinManager)
* skinManager.addSkin(SKIN_BLUE, R.style.app_skin_blue);
* skinManager.addSkin(SKIN_DARK, R.style.app_skin_dark);
* skinManager.addSkin(SKIN_WHITE, R.style.app_skin_white);
* 3.改变主题 changeSkin
*
* // 拿到控件View的 attr,放入. 现在是手动,如何自动???值得思考
* // 1. SimpleArrayMap<String, Integer> skinAttrs;
* // 2. 背景相关的关键字.
* // skinAttrs.put("background", R.attr.tvui_main_layout_background); 比如主布局的
* // skinAttrs.put("background", R.attr.tvui_backgroundColor); // 比如 TvUIButton
* // 3. for (int i = 0; i < skinAttrs.size(); i++)
* // 4. 获取 attr 去获取对应的资源,根据 background 标识,判断对应的View写入背景.
* // 比如 TVUILayout.setBackground...
* </pre>
*/
public class SkinManager {
public static final String BACKGROUND_TAG = "background"; // 背景
public static final String IMAGE_TINT_TAG = "imageTintColor"; // 右侧图标颜色
public static final String ARROW_TINT_TAG = "arrowTintColor"; // 左侧图标颜色
public static final String TEXT_COLOR_TAG = "textColor"; // 文本颜色
public static final String SECOND_TEXT_COLOR_TAG = "secondTextColor"; // 第二文本颜色
private Resources mResources;
private String mPackageName;
private Context mContext;
private static SkinManager instance;
public static SkinManager getInstance(Context context) {
if (null == instance) {
instance = new SkinManager(context);
}
return instance;
}
public SkinManager(Context context) {
mResources = context.getResources();
mPackageName = context.getPackageName();
mContext = context.getApplicationContext();
}
public void changeSkin(Object ob, int skinRes) {
changeSkin(ob, skinRes, null);
}
/**
* 改变主题样式
* // 测试代码
* final SkinManager skinManager = new SkinManager(this);
* skinManager.addSkin(R.style.TestTVUITheme);
* skinManager.changeSkin(this, R.style.TestTVUITheme);
*/
public void changeSkin(Object ob, int skinRes, Resources resources) {
View view = null;
if (null != ob) {
if (ob instanceof Activity) { // 普通的 Activity支持
Activity activity = (Activity) ob;
view = activity.findViewById(android.R.id.content);
} else if (ob instanceof Dialog) { // 系统设置5.0 - Dialog 主题切换支持
Window window = ((Dialog) ob).getWindow();
if (window != null) {
view = window.getDecorView();
}
} else if (ob instanceof View) {
view = (View) ob;
}
mResources = resources != null ? resources : view.getResources();
// 准备进行主题的切换
if (null != view) {
// 主题切换
SkinItem skinItem = new SkinItem(skinRes);
// 获取主题 Theme
Resources.Theme theme = skinItem.getTheme();
// 设置背景图片
ColorStateList bgColorStateList = getAttrColorStateList(
mContext, theme, R.attr.tvui_main_layout_background_color);
// 获取 content view.
view.setBackgroundColor(bgColorStateList.getDefaultColor());
view.getContext().setTheme(skinRes);
// view.getContext().getTheme().setTo(theme);
// 设置主题
setThemeDatas(view, skinRes, theme);
}
}
}
private void setThemeDatas(View view, int skinRes, Resources.Theme theme) {
applyTheme(view, skinRes, theme);
if (view instanceof ViewGroup) {
ViewGroup viewGroup = (ViewGroup) view;
for (int i = 0; i < viewGroup.getChildCount(); i++) {
setThemeDatas(viewGroup.getChildAt(i), skinRes, theme);
}
}
}
private void applyTheme(@NonNull View view, int skinRes, Resources.Theme theme) {
if (view instanceof Button) {
((Button) view)
.setTextColor(getAttrColorStateList(mContext, theme, R.attr.tvui_text_color).getDefaultColor());
}
}
private static TypedValue sTmpValue;
public static ColorStateList getAttrColorStateList(Context context, int attrRes) {
return getAttrColorStateList(context, context.getTheme(), attrRes);
}
public static ColorStateList getAttrColorStateList(Context context, Resources.Theme theme, int attr) {
if (attr == 0) {
return null;
}
if (sTmpValue == null) {
sTmpValue = new TypedValue();
}
if (!theme.resolveAttribute(attr, sTmpValue, true)) {
return null;
}
if (sTmpValue.type >= TypedValue.TYPE_FIRST_COLOR_INT
&& sTmpValue.type <= TypedValue.TYPE_LAST_COLOR_INT) {
return ColorStateList.valueOf(sTmpValue.data);
}
if (sTmpValue.type == TypedValue.TYPE_ATTRIBUTE) {
return getAttrColorStateList(context, theme, sTmpValue.data);
}
if (sTmpValue.resourceId == 0) {
return null;
}
String entryName = context.getResources().getResourceEntryName(sTmpValue.resourceId);
String typeName = context.getResources().getResourceTypeName(sTmpValue.resourceId);
return ContextCompat.getColorStateList(context, sTmpValue.resourceId);
}
public static Drawable getAttrDrawable(Context context, int attr) {
return getAttrDrawable(context, context.getTheme(), attr);
}
public static Drawable getAttrDrawable(Context context, Resources.Theme theme, int attr) {
if (attr == 0) {
return null;
}
if (sTmpValue == null) {
sTmpValue = new TypedValue();
}
if (!theme.resolveAttribute(attr, sTmpValue, true)) {
return null;
}
if (sTmpValue.type >= TypedValue.TYPE_FIRST_COLOR_INT
&& sTmpValue.type <= TypedValue.TYPE_LAST_COLOR_INT) {
return new ColorDrawable(sTmpValue.data);
}
if (sTmpValue.type == TypedValue.TYPE_ATTRIBUTE) {
return getAttrDrawable(context, theme, sTmpValue.data);
}
if (sTmpValue.resourceId != 0) {
return getVectorDrawable(context, sTmpValue.resourceId);
}
return null;
}
public static Drawable getVectorDrawable(Context context, @DrawableRes int resVector) {
try {
return AppCompatResources.getDrawable(context, resVector);
} catch (Exception e) {
return null;
}
}
public static int getAttrDimen(Context context, int attrRes) {
if (sTmpValue == null) {
sTmpValue = new TypedValue();
}
context.getTheme().resolveAttribute(attrRes, sTmpValue, true);
return TypedValue.complexToDimensionPixelSize(sTmpValue.data, context.getResources().getDisplayMetrics());
}
public static float getAttrFloatValue(Context context, int attr) {
return getAttrFloatValue(context.getTheme(), attr);
}
public static float getAttrFloatValue(Resources.Theme theme, int attr) {
if (sTmpValue == null) {
sTmpValue = new TypedValue();
}
theme.resolveAttribute(attr, sTmpValue, true);
return sTmpValue.getFloat();
}
class SkinItem {
private Resources.Theme theme;
private int styleRes;
public SkinItem(int res) {
this.styleRes = res;
}
public int getStyleRes() {
return styleRes;
}
public void setStyleRes(int styleRes) {
this.styleRes = styleRes;
}
Resources.Theme getTheme() {
if (theme == null) {
theme = mResources.newTheme();
theme.applyStyle(styleRes, true);
}
return theme;
}
}
}
/*
https://www.jianshu.com/p/61b79e7f88fc
【】obtainStyledAttributes函数获取属性
*obtainAttributes(AttributeSet set, int[] attrs) //从layout设置的属性集中获取attrs中的属性
*obtainStyledAttributes(int[] attrs) //从系统主题中获取attrs中的属性
*obtainStyledAttributes(int resId,int[] attrs) //从资源文件定义的style中读取属性
*obtainStyledAttributes (AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes)
attrs
attrs:int[],每个方法中都有的参数,就是告诉系统需要获取那些属性的值。
set
set:表示从layout文件中直接为这个View添加的属性的集合,如:android:layout_width="match_parent"。
注意,这里面的属性必然是通过xml配置添加的,也就是由LayoutInflater加载进来的布局或者View`才有这个属性集。
TypedValue typedValue = new TypedValue();
context.getTheme().resolveAttribute(R.attr.yourAttr, typedValue, true);
// For string
typedValue.string
typedValue.coerceToString()
// For other data
typedValue.resourceId
typedValue.data;
*/
Android
1
https://gitee.com/hailongqiu/OpenDemo.git
git@gitee.com:hailongqiu/OpenDemo.git
hailongqiu
OpenDemo
OpenDemo
1d650db07cfc208c12a8ac8be128189fc136339f

搜索帮助

53164aa7 5694891 3bd8fe86 5694891