Android实现皮肤主题修改

news2024/10/7 10:18:49

最近在做App内皮肤切换功能,想了很久方案,写了个皮肤更换工具类,适配N+皮肤种类。

话不多说,直接捋一下我的设计思路,因为我的App默认为黑色主题,因此在做其他皮肤主题时,我的图片命名方式是直接添加后缀。

比如默认主题(黑色)的图片名成为menu。白色主题就叫menu_white  科技主题叫menu_tech,我用的是Mac电脑,设计师做好图后直接批量命名。操作方式如下

白色主题的图片是设计师给我的,命名跟默认主题是一致,则只需要全选图片或者selecter或者shape  右键选择重命名,选择以添加文本方式如图

 

这样所有白色主图的图片都有个white后缀,其他主题也可按照此类方法操作

再结合工具类方法,代码如下

 

    public static int getResourceId(int drawableId){
        String name = SLCApplication.getAppContext().getResources().getString(drawableId);
//        上面转换出来路径为: res/drawable-xhdpi-v4/user_vip.png
//        Log.e(TAG, "getResourceId: name===="+name );
        //得到user_vip.png这个图片名称的字符串
        name = name.substring(name.lastIndexOf("/")+1);
//        Log.e(TAG, "getResourceId: nam0="+name );
        //user_vip.png替换成user_vip_white并去掉.png的后缀
        int themeType = (int)SpUtils.get(SLCApplication.getAppContext(), SkinActivity.THEME_TYPE_KEY,1);
//        Log.e(TAG, "getResourceId: themeType="+themeType );
        if (themeType == 0){
            name = name.replace(name.substring(name.lastIndexOf(".")), "_white");
        }else if (themeType == 2){
            name = name.replace(name.substring(name.lastIndexOf(".")), "_tech");
        }else if (themeType == 3){
            name = name.replace(name.substring(name.lastIndexOf(".")), "_retro");
        }else {
            name = name.replace(name.substring(name.lastIndexOf(".")), "");
        }
//        Log.e(TAG, "getResourceId: name="+name );
        int ids = SLCApplication.getAppContext().getResources().getIdentifier(name,"drawable",SLCApplication.getAppContext().getPackageName());
        if (ids == 0){
            return drawableId;
        }
        return ids;
    }

    public static int getColor(Context context, int colorResId) {
        TypedValue typedValue = new TypedValue();
        TypedArray typedArray = context.obtainStyledAttributes(typedValue.data, new int[] {colorResId});
        int color = typedArray.getColor(0, 0);
        typedArray.recycle();
        return color;
    }
getResourceId方法是通过图片Id 返回对应主题的Id  ,getColor则是设置成为什么颜色。

设置字体方法调用如下:

text_title.setTextColor(ColorAPI.getColor(this, R.attr.whiteColor));

设置图片方法调用如下:

menuImage.setImageDrawable(getDrawable(ColorAPI.getResourceId(R.drawable.menu_selector)));

布局调用如下:

这样的写法是由于我们设置了多主题,可以去自动适配  主题写法如下

在res-->values包中的attrs.xml中的添加颜色属性  如下图

在res-->values包中的styles.xml中的设置主题并设置颜色属性的值如下图

由于我的整个项目的Activity都是继承与自Base ,则只需要在Base的OnCreate方法setContentView函数之前设置好主题,则可以进行自动适配

如图

 

 

工具类中还有几个适配主题的其他方法 ,我整理了下 ,整个类的源码如下

/**
 * ColorAPI
 * Create by lxy on 5/6/23 4:54 PM
 * Copyright © 2022 lxy. All rights reserved.
 **/
public class ColorAPI {

    private static final String TAG = "ColorAPI";

    public static int getResourceId(int drawableId){
        String name = SLCApplication.getAppContext().getResources().getString(drawableId);
//        上面转换出来路径为: res/drawable-xhdpi-v4/user_vip.png
//        Log.e(TAG, "getResourceId: name===="+name );
        //得到user_vip.png这个图片名称的字符串
        name = name.substring(name.lastIndexOf("/")+1);
//        Log.e(TAG, "getResourceId: nam0="+name );
        //user_vip.png替换成user_vip_white并去掉.png的后缀
        int themeType = (int)SpUtils.get(SLCApplication.getAppContext(), SkinActivity.THEME_TYPE_KEY,1);
//        Log.e(TAG, "getResourceId: themeType="+themeType );
        if (themeType == 0){
            name = name.replace(name.substring(name.lastIndexOf(".")), "_white");
        }else if (themeType == 2){
            name = name.replace(name.substring(name.lastIndexOf(".")), "_tech");
        }else if (themeType == 3){
            name = name.replace(name.substring(name.lastIndexOf(".")), "_retro");
        }else {
            name = name.replace(name.substring(name.lastIndexOf(".")), "");
        }
//        Log.e(TAG, "getResourceId: name="+name );
        int ids = SLCApplication.getAppContext().getResources().getIdentifier(name,"drawable",SLCApplication.getAppContext().getPackageName());
        if (ids == 0){
            return drawableId;
        }
        return ids;
    }

    public static int getColor(Context context, int colorResId) {
        TypedValue typedValue = new TypedValue();
        TypedArray typedArray = context.obtainStyledAttributes(typedValue.data, new int[] {colorResId});
        int color = typedArray.getColor(0, 0);
        typedArray.recycle();
        return color;
    }

    public  @interface FrameType {
        int BOTTOM = 0; //底部按钮
        int BOTTOM_LEFT_RIGHT = 1;//底部左右两边按钮
        int FRAME_TWO = 2; //弹出框2行
        int FRAME_THREE = 3;//弹出框3行
    }
    public static void setDrawable(Context context, int type, View textView) {
        //type 0:底部框  1:弹出框底部(取消、确定)
        int themeType = (int) SpUtils.get(context, SkinActivity.THEME_TYPE_KEY,1);
        if (themeType !=2 && themeType !=3)return;
        if (textView.getClass().equals(TextView.class) || textView.getClass().equals(Button.class)){
            ((TextView) textView).setTextColor(getColor(context, R.attr.whiteColor));
        }
        if (themeType == 2){
            if (type == FrameType.BOTTOM)
                 textView.setBackground(context.getDrawable(R.drawable.btn_bottom_frame_tech));
            else if (type == FrameType.BOTTOM_LEFT_RIGHT)
                textView.setBackground(context.getDrawable(R.drawable.btn_frame_tech));
            else if (type == FrameType.FRAME_TWO)
                textView.setBackground(context.getDrawable(R.drawable.tip_frame_tech));
            else if (type == FrameType.FRAME_THREE)
                textView.setBackground(context.getDrawable(R.drawable.new_create_frame_tech));
        }else if (themeType == 3){
            if (type == FrameType.BOTTOM)
                textView.setBackground(context.getDrawable(R.drawable.btn_bottom_frame_retro));
            else if (type == FrameType.BOTTOM_LEFT_RIGHT)
                textView.setBackground(context.getDrawable(R.drawable.btn_frame_retro));
            else if (type == FrameType.FRAME_TWO)
                textView.setBackground(context.getDrawable(R.drawable.tip_frame_retro));
            else if (type == FrameType.FRAME_THREE)
                textView.setBackground(context.getDrawable(R.drawable.new_create_frame_retro));
        }
    }

    public static void setDialogParam(Context context, AlertDialog builder) {
        WindowManager.LayoutParams lp = builder.getWindow().getAttributes();
        lp.gravity = Gravity.CENTER;
        lp.width =  context.getResources().getDisplayMetrics().widthPixels-Util.dip2px(context, 50);
        lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
        builder.getWindow().setAttributes(lp);
    }
}

文章分享给大家不容易,转载请注明出处!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/588865.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Fastjson核心解析器DefaultJSONParser,解析算法递归下降算法,实例解析json的步骤

先恭喜热火没有在3-0的情况下被凯尔特人翻盘,抢七获胜成功晋级总决赛~ 最近的项目用到了fastjson,因为源码比较容易搞到,所以就拿来简单的了解了一下,json的主要功能就是解析json和生成json字符串,今天主要是从解析jso…

基于vue3.0简单的页面使用

基于vue3.0简单的页面使用 项目效果图项目文件图package.jsonmain.jsApp.vueviews/Tutorial.vueviews/TS.vueviews/Docs.vueviews/Community.vueviews/Blog.vueviews/About.vueutils/create.jsxutils/defineCom.jsutils/DragIcon.jsutils/someName.tsutils/TS.tsstores/client.…

win11任务栏时间改成12时制

需求:默认24小时值,想改成12小时3:49 方法:设置-时间和语言-语言和区域-管理语言设置-格式 将时间格式改成带tt的

2022年长三角高校数学建模竞赛C题隧道的升级改造与设计解题全过程文档及程序

2022年长三角高校数学建模竞赛 C题 隧道的升级改造与设计 原题再现: 某地现存一旧式双洞隧道,现计划将该隧道在旧貌基础上升级改造。在升级改造前,需进行定标与设计。考虑到该隧道洞壁附着特殊涂料,无人机在洞内通信信号较差&am…

网络面试题:什么是 TCP/IP?

目录标题 什么是 TCP/IP?1) 网络接口层:2) 网络层:3) 传输层:4) 应用层: 2.数据包3.网络接口层4.网络层1) IP:2)地址解析协议 ARP3)子网 5 传输层1)UDP:2)TCP: 6 应用层运行在TCP协议上的协议:运行在UDP协议上的协议&…

Netty 实现百万级连接服务的难点和优点分析总结

推送服务 还记得一年半前,做的一个项目需要用到 Android 推送服务。和 iOS 不同,Android 生态中没有统一的推送服务。Google 虽然有 Google Cloud Messaging ,但是连国外都没统一,更别说国内了,直接被墙。 所以之前在…

Lua学习笔记:C/C++和Lua的相互调用

前言 本篇在讲什么 C/C和Lua的相互调用 本篇适合什么 适合初学Lua的小白 适合需要C/C和lua结合开发的人 本篇需要什么 对Lua语法有简单认知 对C/C语法有简单认知 依赖Lua5.1的环境 依赖VS 2017编辑器 本篇的特色 具有全流程的图文教学 重实践,轻理论&…

云南智慧档案库综合管理系统建设解决方案

一、智慧档案管理系统建设背景 档案作为一种特殊的文献,是人类社会活动的产物,具有特殊的价值,其价值可以概括为现实价值和历史价值。档案是人类留给国家和社会的宝贵财富,它在经济与社会建设中起着重要的作用。档案是反映一个单…

多重共线性的处理方法

回归分析需要考虑多重共线性问题。多重共线性是指自变量之间存在高度相关性,导致回归模型的系数估计不稳定和假设检验不可靠。在实际应用中,许多自变量之间都可能存在一定程度的相关性,如果没有进行控制,就会导致多重共线性问题的…

设计模式之美-实战二:如何对接口鉴权这样一个功能开发做面向对象分析?

面向对象的三个环节:面向对象分析(OOA)、面向对象设计(OOD)、面向对象编程(OOP)。只知道OOA、OOD、OOP只能说有一个宏观了解,我们更重要的还是要知道“如何做”,也就是&a…

【快应用】多语言适配案例

【关键词】 多语言,$t 【问题背景】 快应用平台的能力会覆盖多个国家地区,平台支持多语言的能力后,可以让一个快应同时支持多个语言版本的切换,开发者无需开发多个不同语言的源码项目,避免给项目维护带来困难。使用系…

子串分值--子串分值和 模拟,找规律

子串分值和 n有十万,需要找规律,O(n^2)不满足要求 分析样例: Ababc 01234 长度是n5 索引下标-对应字符 0A贡献 112 a;ab;---22*1 next a 2; pre a -1 1b贡献 112 b;ba;---42*2 next b 3; pre b -1 2a贡献 1113…

2023年测试前景?测试开发工程师养成记,开发企业级测试平台...

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 测试开发&#xff…

IDS 和 IPS 日志监控

什么是IDS/IPS 入侵检测系统 (IDS) 和入侵防御系统 (IPS) 是监视组织网络中的流量以检测和防止恶意活动和策略违规的网络组件。 入侵检测系统(IDS)和入侵防御系统(IPS)可以说是企业…

C语言学习分享(第八次)------数据的存储

💓博主CSDN主页:杭电码农-NEO💓   ⏩专栏分类:C语言学习分享⏪   🚚代码仓库:NEO的学习日记🚚   🌹关注我🫵带你学习更多C语言知识   🔝🔝 数据的存储 1. 前言🚩2…

现代化智慧档案室建设图文推介

1、防火。建立档案库房防火制度,档案库房附近严禁存放易燃、易爆物品,库房内严禁吸烟,并备有灭火器,经常进行检查更换。 主要设备为:烟雾探测器和感温探测器和七氟丙烷灭火系统。 2、防潮。库房内备有温湿度计&#x…

GB28181 对接海康平台,解决音视频卡顿问题

GB28181 对接海康平台,解决音视频卡顿问题 一、概述二、问题分析1、设备对比分析2、抓包对比分析3、验证分析结果三、总结四、讨论一、概述 设备使用GB28181协议对接海康平台时,发现音频和视频存在卡顿现象,不是一直卡顿,有时候卡有时候不卡,但是卡顿的时候音视频一起卡顿…

炫技操作--递归实现翻转链表(java)

递归实现链表的逆序 leetcode 206题。 翻转链表递归解法普通方式实现链表翻转链表专题 leetcode 206题。 翻转链表 leetcode链接用于测试 题目:描述 将一个链表翻转: 输入:head [1,2,3,4,5] 输出:[5,4,3,2,1] 递归解法 解题思路…

chatgpt赋能python:Python中删除的SEO

Python中删除的SEO Python是一个强大的编程语言,它广泛应用于各种领域,包括SEO。在SEO领域中,Python可以用来处理各种数据,包括删除不必要的数据。本文将介绍如何在Python中删除SEO数据。 什么是SEO数据? SEO是搜索…

代码创造的欢乐世界-通用人工智能让儿童熟练应用编程

想要复杂的参考这一篇,使用云平台即可完成: 美美的圣诞树画出来-CoCube- 把圣诞树换成六一儿童节主题的就可以啦。 这一篇是使用chatgpt类应用,给出关键提示词,代码自动生成哦。 神十六发射成功,科技工作者博士学位…