package ren.solid.skinloader.load;
import android.content.Context;
import android.content.res.Resources;
import android.support.v4.view.LayoutInflaterFactory;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import java.util.ArrayList;
import java.util.List;
import ren.solid.skinloader.attr.DynamicAttr;
import ren.solid.skinloader.attr.SkinAttr;
import ren.solid.skinloader.util.L;
import ren.solid.skinloader.attr.AttrFactory;
import ren.solid.skinloader.config.SkinConfig;
import ren.solid.skinloader.entity.SkinItem;
import ren.solid.skinloader.util.ListUtils;
/**
* Created by _SOLID
* Date:2016/4/13
* Time:21:19
* <p>
* 自定义的InflaterFactory,用来代替默认的InflaterFactory
* 参考链接:http://willowtreeapps.com/blog/app-development-how-to-get-the-right-layoutinflater/
*/
public class SkinInflaterFactory implements LayoutInflaterFactory {
private static String TAG = "SkinInflaterFactory";
/**
* 存储那些有皮肤更改需求的View及其对应的属性的集合
*/
private List<SkinItem> mSkinItems = new ArrayList<SkinItem>();
@Override
public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
// 检测当前View是否有更换皮肤的需求
boolean isSkinEnable = attrs.getAttributeBooleanValue(SkinConfig.NAMESPACE, SkinConfig.ATTR_SKIN_ENABLE, false);
if (!isSkinEnable) {
return null;//返回空就使用默认的InflaterFactory
}
View view = createView(context, name, attrs);
if (view == null) {//没有找到这个View
return null;
}
parseSkinAttr(context, attrs, view);
return view;
}
/**
* 通过name去实例化一个View
*
* @param context
* @param name 要被实例化View的全名.
* @param attrs View在布局文件中的XML的属性
* @return View
*/
private View createView(Context context, String name, AttributeSet attrs) {
Log.i(TAG, "createView:" + name);
View view = null;
try {
if (-1 == name.indexOf('.')) {
if ("View".equals(name)) {
view = LayoutInflater.from(context).createView(name, "android.view.", attrs);
}
if (view == null) {
view = LayoutInflater.from(context).createView(name, "android.widget.", attrs);
}
if (view == null) {
view = LayoutInflater.from(context).createView(name, "android.webkit.", attrs);
}
} else {
view = LayoutInflater.from(context).createView(name, null, attrs);
}
L.i(TAG, "about to create " + name);
} catch (Exception e) {
L.e(TAG, "error while create 【" + name + "】 : " + e.getMessage());
view = null;
}
return view;
}
/**
* 搜集可更换皮肤的属性
*
* @param context
* @param attrs
* @param view
*/
private void parseSkinAttr(Context context, AttributeSet attrs, View view) {
List<SkinAttr> viewAttrs = new ArrayList<SkinAttr>();//存储View可更换皮肤属性的集合
for (int i = 0; i < attrs.getAttributeCount(); i++) {//遍历当前View的属性
String attrName = attrs.getAttributeName(i);//属性名
String attrValue = attrs.getAttributeValue(i);//属性值
if (!AttrFactory.isSupportedAttr(attrName)) {
continue;
}
if (attrValue.startsWith("@")) {//也就是引用类型,形如@color/red
try {
int id = Integer.parseInt(attrValue.substring(1));//资源的id
String entryName = context.getResources().getResourceEntryName(id);//入口名,例如text_color_selector
String typeName = context.getResources().getResourceTypeName(id);//类型名,例如color、background
SkinAttr mSkinAttr = AttrFactory.get(attrName, id, entryName, typeName);
L.i("parseSkinAttr", "view:" + view.getClass().getSimpleName());
L.i("parseSkinAttr", "attrName:" + attrName + " | attrValue:" + attrValue);
L.i("parseSkinAttr", "id:" + id);
L.i("parseSkinAttr", "entryName:" + entryName);
L.i("parseSkinAttr", "typeName:" + typeName);
if (mSkinAttr != null) {
viewAttrs.add(mSkinAttr);
}
} catch (NumberFormatException e) {
e.printStackTrace();
} catch (Resources.NotFoundException e) {
e.printStackTrace();
}
}
}
if (!ListUtils.isEmpty(viewAttrs)) {
SkinItem skinItem = new SkinItem();
skinItem.view = view;
skinItem.attrs = viewAttrs;
mSkinItems.add(skinItem);
if (SkinManager.getInstance().isExternalSkin()) {//如果当前皮肤来自于外部
skinItem.apply();
}
}
}
/**
* 应用皮肤
*/
public void applySkin() {
if (ListUtils.isEmpty(mSkinItems)) {
return;
}
for (SkinItem si : mSkinItems) {
if (si.view == null) {
continue;
}
si.apply();
}
}
/**
* 清除有皮肤更改需求的View及其对应的属性的集合
*/
public void clean() {
if (ListUtils.isEmpty(mSkinItems)) {
return;
}
for (SkinItem si : mSkinItems) {
if (si.view == null) {
continue;
}
si.clean();
}
}
public void addSkinView(SkinItem item) {
mSkinItems.add(item);
}
/**
* 动态添加那些有皮肤更改需求的View,及其对应的属性
*
* @param context
* @param view
* @param attrName 属性名
* @param attrValueResId 属性资源id
*/
public void dynamicAddSkinEnableView(Context context, View view, String attrName, int attrValueResId) {
int id = attrValueResId;
String entryName = context.getResources().getResourceEntryName(id);
String typeName = context.getResources().getResourceTypeName(id);
SkinAttr mSkinAttr = AttrFactory.get(attrName, id, entryName, typeName);
SkinItem skinItem = new SkinItem();
skinItem.view = view;
List<SkinAttr> viewAttrs = new ArrayList<SkinAttr>();
viewAttrs.add(mSkinAttr);
skinItem.attrs = viewAttrs;
skinItem.apply();
addSkinView(skinItem);
}
/**
* 动态添加那些有皮肤更改需求的View,及其对应的属性集合
*
* @param context
* @param view
* @param pDAttrs
*/
public void dynamicAddSkinEnableView(Context context, View view, List<DynamicAttr> pDAttrs) {
List<SkinAttr> viewAttrs = new ArrayList<SkinAttr>();
SkinItem skinItem = new SkinItem();
skinItem.view = view;
for (DynamicAttr dAttr : pDAttrs) {
int id = dAttr.refResId;
String entryName = context.getResources().getResourceEntryName(id);
String typeName = context.getResources().getResourceTypeName(id);
SkinAttr mSkinAttr = AttrFactory.get(dAttr.attrName, id, entryName, typeName);
viewAttrs.add(mSkinAttr);
}
skinItem.attrs = viewAttrs;
skinItem.apply();
addSkinView(skinItem);
}
}