android 动态换肤功能笔记

供参考


import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.ColorStateList;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.util.ArrayMap;
import android.util.AttributeSet;
import android.util.Log;
import android.view.*;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.FragmentActivity;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewbinding.ViewBinding;
import com.bumptech.glide.Glide;
import com.fast_gathering.Util.StatusBarUtil;
import com.fast_gathering.app.BindingActivity;
import com.fast_gathering.plugin.app.Activity;
import com.google.android.material.appbar.AppBarLayout;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static android.content.Context.MODE_PRIVATE;

public class SkinFactoryLayoutInflaterFactory implements LayoutInflater.Factory {
    private AppCompatActivity activity;

    public SkinFactoryLayoutInflaterFactory(AppCompatActivity activity) {
        this.activity = activity;
    }

    // 默认前缀包名列表
    private static final String[] sClassPrefixList = {"android.widget.", "android.view.", "android.webkit."};
    private static final Object[] mConstructorArgs = new Object[2];
    private static final Map<String, Constructor<? extends View>> sConstructorMap = new ArrayMap<>();
    private static final Class<?>[] sConstructorSignature = new Class[]{Context.class, AttributeSet.class};

    private final List<skin> viewList = new ArrayList<>();

    class skin {
        private Context context;
        private AttributeSet attrs;
        private String name;
        private View view;

        public Context getContext() {
            return context;
        }

        public void setContext(Context context) {
            this.context = context;
        }

        public AttributeSet getAttrs() {
            return attrs;
        }

        public void setAttrs(AttributeSet attrs) {
            this.attrs = attrs;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public View getView() {
            return view;
        }

        public void setView(View view) {
            this.view = view;
        }
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull String name, @NonNull Context context, @NonNull AttributeSet attrs) {
        View view = createViewFromTag(context, name, attrs);
        if (view instanceof AppBarLayout) {
            try {
                initSkin(context, view, name, attrs);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
        if (IsSkin(attrs)) {
            //需要更换主题
            try {
                initSkin(context, view, name, attrs);
                skin skin = new skin();
                skin.setContext(context);
                skin.setAttrs(attrs);
                skin.setView(view);
                skin.setName(name);
                viewList.add(skin);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
        return view;
    }

    /**
     * 重新初始化
     */
    public void initSkin() {
        for (skin view : viewList) {
            try {
                if (view.view != null) {
                    initSkin(view.context, view.view, view.name, view.attrs);
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    }

    private void initSkin(Context context, View view, String name, AttributeSet attributeSet) throws JSONException {
        int skin_type = getSkin(attributeSet);
        SharedPreferences theme = context.getSharedPreferences("set_Themes", MODE_PRIVATE);
        String json = theme.getString("json", getSkin().toString());
        JSONObject jsonObject = new JSONObject(json);
        //状态栏字体颜色
        if (!jsonObject.isNull("mode") && activity != null) {
            int mode = jsonObject.getInt("mode");
            if (mode == 0) {
                StatusBarUtil.setLightMode(activity);
            } else {
                StatusBarUtil.setDarkMode(activity);
            }
        }

        if (!jsonObject.isNull("StatusBar") && activity != null) {
            JSONObject StatusBar = jsonObject.getJSONObject("StatusBar");
            String color = StatusBar.getString("Color");
            StatusBarUtil.setColor(activity, Color.parseColor(color), 0);
        }

        if (!jsonObject.isNull(name)) {


            JSONObject value = jsonObject.getJSONObject(name);

            if (name.equals("androidx.appcompat.widget.Toolbar")) {
                Toolbar toolbar = (Toolbar) view;
                String Tint = value.getString("Tint");
                String TitleColor = value.getString("TitleColor");
                String background = value.getString("Background");

                toolbar.setTitleTextColor(Color.parseColor(TitleColor));
                if (toolbar.getNavigationIcon() != null) {
                    toolbar.getNavigationIcon().setTint(Color.parseColor(Tint));
                }
                if (background.startsWith("#")) {
                    toolbar.setBackgroundColor(Color.parseColor(background));
                } else {
                    File file = context.getDir("Skin", MODE_PRIVATE);
                    File file1 = new File(file, "themes");
                    toolbar.setBackground(BitmapDrawable.createFromPath(new File(file1, background).getAbsolutePath()));
                }

                if (toolbar.getMenu() != null) {
                    String type = value.getString("Menu");
                    if (type.equals("menu_white")) {
                        toolbar.setPopupTheme(R.style.menu_white);
                    } else if (type.equals("menu_black")) {
                        toolbar.setPopupTheme(R.style.menu_black);
                    }
                }
            }

            if (name.equals("Toolbar")) {
                android.widget.Toolbar toolbar = (android.widget.Toolbar) view;
                toolbar.setFitsSystemWindows(true);
                String Tint = value.getString("Tint");
                String TitleColor = value.getString("TitleColor");
                String background = value.getString("Background");
                toolbar.setTitleTextColor(Color.parseColor(TitleColor));
                if (toolbar.getNavigationIcon() != null) {
                    Log.d("颜色", TitleColor);
                    toolbar.getNavigationIcon().setTint(Color.parseColor(Tint));
                }
                toolbar.setBackgroundColor(Color.parseColor(background));

                if (toolbar.getMenu() != null) {
                    String type = value.getString("Menu");
                    if (type.equals("menu_white")) {
                        toolbar.setPopupTheme(R.style.menu_white);
                    } else if (type.equals("menu_black")) {
                        toolbar.setPopupTheme(R.style.menu_black);
                    }
                }
            }

            if (name.equals("RelativeLayout")) {
                String background = value.getString("Background");
                view.setBackgroundColor(Color.parseColor(background));
            }

            if (name.equals("ImageButton")) {
                ImageButton imageButton = (ImageButton) view;
                String Tint = value.getString("Tint");
                imageButton.setImageTintList(ColorStateList.valueOf(Color.parseColor(Tint)));
            }

            if (name.equals("TextView")) {
                TextView textView = (TextView) view;
                String color;
                if (skin_type == 1) {
                    color = value.getString("TextColor1");
                } else {
                    color = value.getString("TextColor");
                }
                textView.setTextColor(Color.parseColor(color));
            }

            if (name.equals("androidx.appcompat.widget.SearchView")) {
                SearchView searchView = (SearchView) view;
                String tint = value.getString("Tint");
                ImageView search_close_btn = searchView.findViewById(androidx.appcompat.R.id.search_close_btn);
                ImageView search_go_btn = searchView.findViewById(androidx.appcompat.R.id.search_go_btn);
                ImageView button = searchView.findViewById(androidx.appcompat.R.id.search_button);
                ImageView search_mag_icon = searchView.findViewById(androidx.appcompat.R.id.search_mag_icon);
                //ImageView search_edit_frame = searchView.findViewById(androidx.appcompat.R.id.search_edit_frame);
                //ImageView search_plate=searchView.findViewById(androidx.appcompat.R.id.search_plate);

                if (button.getDrawable() != null) {
                    button.getDrawable().setTint(Color.parseColor(tint));
                }

                if (search_mag_icon != null) {
                    search_mag_icon.setImageTintList(ColorStateList.valueOf(Color.parseColor(tint)));
                }
                search_go_btn.setImageTintList(ColorStateList.valueOf(Color.parseColor(tint)));
                search_close_btn.setImageTintList(ColorStateList.valueOf(Color.parseColor(tint)));
                button.setImageTintList(ColorStateList.valueOf(Color.parseColor(tint)));
            }

            if (name.equals("com.google.android.material.appbar.AppBarLayout")) {
                String background = value.getString("Background");
                AppBarLayout appBarLayout = (AppBarLayout) view;
                appBarLayout.setFitsSystemWindows(true);
                appBarLayout.setBackgroundColor(Color.parseColor(background));
            }

            if (name.equals("androidx.recyclerview.widget.RecyclerView")) {
                String background = value.getString("Background");
                RecyclerView recyclerView = (RecyclerView) view;
                if (recyclerView.getBackground() != null) {
                    recyclerView.getBackground().setTint(Color.parseColor(background));
                }
            }

        }
    }


    public static JSONObject getSkin() {
        try {
            JSONObject attributeSet = new JSONObject();
            attributeSet.put("mode", 0);
            attributeSet.put("themes_id", 0);
            attributeSet.put("name", "默认主题");
            attributeSet.put("color", "#FFFFFF");
            attributeSet.put("introduce", "极致简约的白色");

            JSONObject StatusBar = new JSONObject();
            StatusBar.put("Color", "#FFFFFF");
            attributeSet.put("StatusBar", StatusBar);

            JSONObject RecyclerView = new JSONObject();
            RecyclerView.put("Background", "#FFFFFF");
            attributeSet.put("androidx.recyclerview.widget.RecyclerView", RecyclerView);

            JSONObject TextView = new JSONObject();
            TextView.put("TextColor", "#000000");
            TextView.put("TextColor1", "#997F7F7F");
            attributeSet.put("TextView", TextView);

            JSONObject SearchView = new JSONObject();
            SearchView.put("Tint", "#000000");
            attributeSet.put("androidx.appcompat.widget.SearchView", SearchView);

            JSONObject RelativeLayout = new JSONObject();
            RelativeLayout.put("Background", "#FFFFFF");
            attributeSet.put("RelativeLayout", RelativeLayout);

            JSONObject toolbar = new JSONObject();
            toolbar.put("Menu", "menu_white");
            toolbar.put("Background", "#FFFFFF");
            toolbar.put("TitleColor", "#000000");
            toolbar.put("Tint", "#000000");
            attributeSet.put("androidx.appcompat.widget.Toolbar", toolbar);

            attributeSet.put("Toolbar", toolbar);

            JSONObject ImageButton = new JSONObject();
            ImageButton.put("Tint", "#000000");
            attributeSet.put("ImageButton", ImageButton);

            JSONObject AppBarLayout = new JSONObject();
            AppBarLayout.put("Background", "#FFFFFF");
            attributeSet.put("com.google.android.material.appbar.AppBarLayout", AppBarLayout);
            return attributeSet;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new JSONObject();
    }

    /**
     * 返回需要设置的类型
     *
     * @param attrs 数据
     * @return 默认0
     */
    private int getSkin(AttributeSet attrs) {
        //获取AttributeSet中所有的XML属性的数量
        int count = attrs.getAttributeCount();
        //遍历AttributeSet中的XML属性
        for (int i = 0; i < count; i++) {
            String attributeName = attrs.getAttributeName(i);
            if (attributeName.equals("skin")) {
                //获取attr的资源ID
                return attrs.getAttributeIntValue(i, 0);
            }
        }
        return 0;
    }

    /**
     * @param attrs 数据
     * @return 判断是否需要更换主题
     */
    private boolean IsSkin(AttributeSet attrs) {
        //获取AttributeSet中所有的XML属性的数量
        int count = attrs.getAttributeCount();
        //遍历AttributeSet中的XML属性
        for (int i = 0; i < count; i++) {
            //获取attr的资源ID
            String attributeName = attrs.getAttributeName(i);
            if (attributeName.equals("is_skin")) {
                return true;
            }
        }
        return false;
    }

    /**
     * copy android.support.v7.app.AppcompatViewInflater #createViewFromTag()
     *
     * @param context
     * @param name
     * @param attrs
     * @return
     */
    public static View createViewFromTag(Context context, String name, AttributeSet attrs) {
        if (name.equals("view")) {
            name = attrs.getAttributeValue(null, "class");
        }

        try {
            mConstructorArgs[0] = context;
            mConstructorArgs[1] = attrs;

            if (-1 == name.indexOf('.')) {
                for (int i = 0; i < sClassPrefixList.length; i++) {
                    final View view = createView(context, name, sClassPrefixList[i]);
                    if (view != null) {
                        return view;
                    }
                }
                return null;
            } else {
                return createView(context, name, null);
            }
        } catch (Exception e) {
            // We do not want to catch these, lets return null and let the actual LayoutInflater
            // try
            return null;
        } finally {
            // Don't retain references on context.
            mConstructorArgs[0] = null;
            mConstructorArgs[1] = null;
        }
    }


    /**
     * 创建view
     *
     * @param context
     * @param name
     * @param prefix
     * @return
     * @throws InflateException
     */
    private static View createView(Context context, String name, String prefix) throws InflateException {
        Constructor<? extends View> constructor = sConstructorMap.get(name);

        try {
            if (constructor == null) {
                // Class not found in the cache, see if it's real, and try to add it
                Class<? extends View> clazz = context.getClassLoader().loadClass(prefix != null ? (prefix + name) : name).asSubclass(View.class);

                constructor = clazz.getConstructor(sConstructorSignature);
                sConstructorMap.put(name, constructor);
            }
            constructor.setAccessible(true);
            return constructor.newInstance(mConstructorArgs);
        } catch (Exception e) {
            // We do not want to catch these, lets return null and let the actual LayoutInflater
            // try
            return null;
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值