资讯 小学 初中 高中 语言 会计职称 学历提升 法考 计算机考试 医护考试 建工考试 教育百科
栏目分类:
子分类:
返回
空麓网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
空麓网 > 计算机考试 > 软件开发 > 后端开发 > .Net

【官方推荐方式】【原创】安卓换肤踩坑纯色模式app使用attr轻松实现定制颜色主题和深色主题...

.Net 更新时间: 发布时间: 计算机考试归档 最新发布

【官方推荐方式】【原创】安卓换肤踩坑纯色模式app使用attr轻松实现定制颜色主题和深色主题...

如果在网上搜换肤,方案五花八门,但是根据app的需求,以及无设计师的情况下,基本上简约风格app,这种风格下只需要几个颜色就行了,根本不需要动态从磁盘加载皮肤apk,而且通过反射操作侵入性太强,因此attr大法才是最适合目前的我所做的app实现。

网上的换肤方法侵入性太强,而纯色app不需要各种花式的皮肤,基本上2三套颜色就行了,主色,次色,而其他则非黑即白。深色模式实现就更简单了,用着色tint就实现了。

经过了几天的研究发现,动态修改setTheme是有bug的, bug就是状态栏颜色和actionbar在未在activity定义attr背景的情况下实现修改actionbar的就有这个bug,2015年在stackoverflow网站上就有人提出解决方法,这个解决方法是没有办法的方法,需要在baseactivity进行判断,如果有actionbar就设置actionbar颜色,

以及设置状态栏颜色。

达到的效果

在颜色选择器中是可以直接使用实现的属性?attr
而在drawable,则需要包裹一层drawable引用color,直接使用color属性也是会报错的,

颜色主题需要注意的事项

drawable要使用颜色属性只能包裹一层shape




第三方自定义ui 有的是只支持颜色不支持attr的。则需要进行额外适配处理,
其处理方式就是根据属性查找对应的颜色 或者id (colorres)
颜色属性找颜色

public static int attrFetchColor(int attrColor) {
        int[] attribute = new int[]{attrColor};
        TypedArray array = AppContext.getInstance().getTheme().obtainStyledAttributes(attribute);
        int color = array.getColor(0, AppContext.getInstance().getResources().getColor(R.color.themeColor));
        array.recycle();
        return color;
    }

查找id

public static int attrFetchColorId(int attrColor) {
int[] attribute = new int[]{attrColor};
TypedArray array = AppContext.getInstance().getTheme().obtainStyledAttributes(attribute);
int colorID = array.getResourceId(0, R.color.themeColor);
array.recycle();
return colorID;
}

在baseactivity onCreate中修改状态栏颜色

public static void updateActionBarAndStatusColor(Activity activity) {
        if (activity instanceof AppCompatActivity) {
            AppCompatActivity appCompatActivity = (AppCompatActivity) activity;
            ActionBar supportActionBar = appCompatActivity.getSupportActionBar();
            if (supportActionBar != null) {
                int i = AppUtils.attrFetchColor(R.attr.defaultThemeColor);
                supportActionBar.setBackgroundDrawable(new ColorDrawable(i));
            }

        }
        android.app.ActionBar actionBar = activity.getActionBar();
        if (actionBar != null) {
            int color = AppUtils.attrFetchColor(R.attr.defaultThemeColor);
            actionBar.setBackgroundDrawable(new ColorDrawable(color));
        }

        if (Build.VERSION.SDK_INT >= 21) {
//            getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
//            getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            int statusBarBackground = AppUtils.attrFetchColor(R.attr.statusBarBackground);


            Window window = activity.getWindow();
//            window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
//            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
//            window.setStatusBarColor(backgroundColor);
            window.setStatusBarColor(statusBarBackground);
        }


    }

适配起来挺快的,通过各种批量替换
但是需要注意的是,第三方对颜色适配做的很烂,哪怕大家众所周知的smartrefresh也不支持属性引用颜色。 因此主要的适配就是处理第三方框架的问题,
这个适配工作基本上一天就搞定了。
另外花的实际是纠结研究为啥actionbar和状态栏颜色通过setTheme无效花费了很多时间,在attach里面替换,以及研究theme的各种方法,以及引用再引用的方式也解决不了问题,
最后既然无效我只能另外走方法了,强制设置。

attr.xml定义


    

其实现在每一个主题都实现了,

下面附上theme.xml 仔细看 都实现了defaultThemeColor defaultThemeColorSecond 属性,




    


    


    

    






    


    

    
    

    














    

color实现

@color/light_blue_A200
    @color/purple_200
    @color/purple_200
    @color/black_overlay
    @color/black
    @color/teal_200
    @color/teal_200
    @color/black







    @color/light_blue_A200
    @color/purple_200
    @color/purple_200
    @color/black_overlay
    @color/black





    @color/light_blue_A200
    @color/purple_200
    @color/purple_200
    @color/black_overlay
    @color/black



    @color/light_blue_A200
    @color/purple_200
    @color/purple_200
    @color/black_overlay
    @color/black




    @color/light_blue_A200
    @color/purple_200
    @color/purple_200
    @color/black_overlay
    @color/black


    @color/light_blue_A200
    @color/purple_200
    @color/purple_200
    @color/black_overlay
    @color/black

深色主题values-night themes.xml
把正常颜色的拷贝过来然后指定颜色就行了,
修改主题的代码 baseactivityonCreate调用在setContentView之前

fun applySetting(context: Context?):Int {
        var themeId = 0;
        // 检查主题
        val themeModeInt = getSpfThemeMode()
        val themeMode = ThemeMode.parseOfInt(themeModeInt)
        var containActionBar: Boolean = false;
        var actName: String = "";
        if (context is AppCompatActivity) {
            var act: AppCompatActivity = (context as AppCompatActivity);
            if (act.supportActionBar is WindowDecorActionBar) {
                containActionBar = true;
            }
            actName =
                context.javaClass.simpleName + " ,是否已支持actionBar " + containActionBar;

        }
        if (themeMode == ThemeMode.BLUE_THEME) {
            if (containActionBar) {
                themeId = R.style.Theme_MyApplication_Blue
            } else {
                themeId = R.style.Theme_MyApplication_Blue_NoActionBar
            }
            Log.w("ThemeStyle", "蓝色主题 $actName");
        } else if (themeMode == ThemeMode.YELLOW_THEME) {
            if (containActionBar) {
                themeId = R.style.Theme_MyApplication_Yellow
            } else {
                themeId = R.style.Theme_MyApplication_Yellow_NoActionBar
            }
            Log.w("ThemeStyle", "黄色主题 $actName");
        } else if (themeMode == ThemeMode.PURPLE_THEME) {
            Log.w("ThemeStyle", "紫色主题 $actName");
            if (containActionBar) {
                themeId = R.style.Theme_MyApplication_PURPLE
            } else {
                themeId = R.style.Theme_MyApplication_PURPLE_NoActionBar
            }
        } else if (themeMode == ThemeMode.GREEN_THEME) {
            Log.w("ThemeStyle", "绿色主题 $actName");
            if (containActionBar) {
                themeId = R.style.Theme_MyApplication_GREEN
            } else {
                themeId = R.style.Theme_MyApplication_GREEN_NoActionBar;
            }
        } else if (themeMode == ThemeMode.BLACK_THEME) {
            Log.w("ThemeStyle", "黑色主题 $actName");
            if (containActionBar) {
                themeId = R.style.Theme_MyApplication_BLACK;
            } else {
                themeId = R.style.Theme_MyApplication_BLACK_NoActionBar;
            }
        } else {
            Log.w("ThemeStyle", "其他主题模式 $actName");
        }
        if(themeId!=0){
            context?.setTheme(themeId)
//            return themeId;
        }
        AppCompatDelegate.setDefaultNightMode(
            when (themeMode) {
                ThemeMode.MODE_ALWAYS_ON -> AppCompatDelegate.MODE_NIGHT_YES
                ThemeMode.MODE_ALWAYS_OFF -> AppCompatDelegate.MODE_NIGHT_NO
                ThemeMode.MODE_FOLLOW_SYSTEM -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
                else -> {
                    AppCompatDelegate.MODE_NIGHT_NO
                }
            }


        )
                return themeId

    }

如果不为0,

if (color != 0) {
//            getTheme().applyStyle(color, true);
            AppUtils.updateActionBarAndStatusColor(this);
        }

另外补充一点,按钮这些一般我都没有修改在每一个activity xml设置的,遵循material design以及theme的写法,全局就可以进行操作的,在就完成了适配,
主要的适配工作还是处理selector的颜色以及第三方框架引用了颜色的情况,另外处理深色兼容的适配。

转载请注明:文章转载自 http://www.konglu.com/
本文地址:http://www.konglu.com/it/983432.html
免责声明:

我们致力于保护作者版权,注重分享,被刊用文章【【官方推荐方式】【原创】安卓换肤踩坑纯色模式app使用attr轻松实现定制颜色主题和深色主题...】因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理,本文部分文字与图片资源来自于网络,转载此文是出于传递更多信息之目的,若有来源标注错误或侵犯了您的合法权益,请立即通知我们,情况属实,我们会第一时间予以删除,并同时向您表示歉意,谢谢!

我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2023 成都空麓科技有限公司

ICP备案号:蜀ICP备2023000828号-2