android 换肤框架详解1-换肤逻辑基本-CSDN博客

android 换肤框架详解2-LayoutInflater源码解析-CSDN博客

android 换肤框架详解3-自动换肤原理梳理-CSDN博客

  • 换肤框架流程

1,通过AssetManager获取换肤的资源文件

2,通过原文件中的resId获取到res名称和res类型,比如resId未R.color.red,这里的名称就是red,类型就是color

3,在换肤的资源文件AssetManager中,用原文件的resId的res名称和res类型获取到换肤资源文件中的ResId,在通过AssetManager.getXXX拿到对应的资源

4,将拿到的资源文件部署到View

  • 代码模块

1,创建资源包

由于资源包只需要里面的资源文件,多余的内容都可以删除到,这里只留如下内容

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true" /></manifest>

gradle中不需要其他的引用包

build.gradle.kts

plugins {id("com.android.application")
}android {namespace = "com.kx.skin"compileSdk = 33defaultConfig {applicationId = "com.kx.skin"minSdk = 28targetSdk = 33versionCode = 1versionName = "1.0"testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"}buildTypes {release {isMinifyEnabled = falseproguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"),"proguard-rules.pro")}}compileOptions {sourceCompatibility = JavaVersion.VERSION_1_8targetCompatibility = JavaVersion.VERSION_1_8}
}dependencies {
}

在原本的app和换肤资源的app中同时创建名称相同的资源

将编译好的skin apk放到assets目录下

  • 创建资源文件的AssetManager
    public static Resources getThemeResources(Context context) {try {//通过反射创建AssetManager
//            AssetManager assetManager = AssetManager.class.newInstance();
//            Method add = assetManager.getClass().getDeclaredMethod("addAssetPath", String.class);//通过反射加载路径
//            int cookie = (int) add.invoke(assetManager, "/sdcard/skin/skin.skin");//将assets中的文件拷贝到自己私有的文件中File skinFile = copyAssetToFiles(context,"skin-debug.apk",        // assets 下的相对路径"skin-debug.apk");            // 目标文件名boolean exists = skinFile.exists();   // true 表示存在Log.e(TAG, "加载文件 exists " + exists + " getAbsolutePath " + skinFile.getAbsolutePath());// 创建资源ResourcesAssetManager assetManager = new AssetManager();int cookie = assetManager.addAssetPath(skinFile.getAbsolutePath());if (cookie == 0) {Log.e(TAG, "加载失败,路径无效或权限不足");}Resources oldRes = context.getResources();Resources newRes = new Resources(assetManager,oldRes.getDisplayMetrics(),oldRes.getConfiguration());return newRes;} catch (Throwable e) {e.printStackTrace();Log.d(TAG, "Throwable " + e);}return null;}

2,在换肤的资源文件AssetManager中,用原文件的resId的res名称和res类型获取到换肤资源文件中的ResId,在通过AssetManager.getXXX拿到对应的资源

    public static int getThemeResourcesColorResId(Context context, int resId) {Log.d(TAG, "getThemeResourcesColor resId " + resId);Resources resources = context.getResources();//包名:资源类型/资源名
//        String resName = resources.getResourceName(resId);//返回格式:ic_launcher(仅资源名)R.drawable.ic_launcher,R.color.ic_launcherString resName = resources.getResourceEntryName(resId);//资源类型类型drawable,colorString typeName = resources.getResourceTypeName(resId);Log.d(TAG, "getThemeResourcesColor resName " + resName);Log.d(TAG, "getThemeResourcesColor typeName " + typeName);//获取主题资源文件Resources newResources = getThemeResources(context);//通过资源名称,获取到资源IDint newResId = newResources.getIdentifier(resName,        // 资源名typeName,           // 资源类型"com.kx.skin" // 应用包名);Log.d(TAG, "getThemeResourcesColor newResId " + newResId);//通过资源ID,获取到对应资源的值int newColorResId = newResources.getColor(newResId, null);Log.d(TAG, "getThemeResourcesColor newColorResId " + newColorResId);return newColorResId;}

代码调用

                int resId = ThemeModeChange.getThemeResourcesColorResId(ThemeActivity.this,R.color.content);tv_content.setBackgroundColor(resId);

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

NEON性能优化总结

转自 NEON优化&#xff1a;性能优化经验总结-CSDN博客 NEON优化&#xff1a;性能优化经验总结 1. 什么是 NEON Arm Adv SIMD 历史 2. 寄存器 3. NEON 命名方式 4. 优化技巧 5. 优化 NEON 代码(Armv7-A内容&#xff0c;但区别不大) 5.1 优化 NEON 汇编代码 …

计算机网络摘星题库800题笔记 第2章 物理层

第2章 物理层2.1 物理层概述题组闯关1.采用以下哪种设备&#xff0c;可以使数字信号传输得更远 ( )。 A. 放大器 B. 中继器 C. 网桥 D. 路由器1.【参考答案】B 【解析】选项 A 放大器只是单纯地放大信号、抑制噪音和干扰。选项 B 中继器是把一根线缆中的电或者光信号传递给另一…

导入文件到iPhone实现

我们有时候开发需要加载一些自己的文件&#xff0c;这个时候就需要导入文件到iPhone等设备。在info里面open as source code&#xff0c;加入如下配置&#xff1a;<!-- 开启 iTunes / Finder 文件共享 --><key>UIFileSharingEnabled</key><true/>或者o…

Ubuntu Server系统安装磁盘分区方案

最近打算把家里的旧电脑利用起来&#xff0c;装上Ubuntu Server 24.04.3 LTS作为一个家用NAS服务器&#xff0c;但是给旧电脑安装系统时遇到了一些问题&#xff0c;遂记录下来 GPT分区与MBR分区 GPT 指的是 GUID Partition Table&#xff08;全局唯一标识分区表&#xff09;&am…

1小时 MySQL 数据库基础速通

目录 一、MySQL安装配置 1、下载mysql 2、下载mysql-shell 二、MySQL基本概念 1. 数据库&#xff08;Database&#xff09; 2. 表&#xff08;Table&#xff09; 3. 数据类型&#xff08;Data Type&#xff09; 4. 主键&#xff08;Primary Key&#xff09; 5. 索引&am…

HTTP应用层协议-长连接

HTTP应用层协议-长连接 关于 connection 报头 HTTP 中的 Connection 字段是 HTTP 报文头的一部分&#xff0c;它主要用于控制和管理客户端与服务器之间的连接状态 核心作用 • 管理持久连接&#xff1a;Connection 字段还用于管理持久连接&#xff08;也称为长连接&#xff09;…

2020/12 JLPT听力原文 问题一 4番

4番&#xff1a;ホテルの受付で女の人と男の人が話しています。女の人はどこでパソコンを使いますか。女&#xff1a;すみません、パソコンの貸出ってできますか。部屋で仕事をしたいんですけど。 男&#xff1a;申し訳ございません。貸出はしていないんですが、二階にビジネス…

《在 Spring Boot 中安全使用 Qwen API-KEY:环境变量替代明文配置的最佳实践》

《在 Spring Boot 中安全使用 Qwen API-KEY&#xff1a;环境变量替代明文配置的最佳实践》 想要的效果其实就是 把 Qwen API-KEY 放到系统环境变量中&#xff0c;然后在 application.yml 里通过占位符读取&#xff0c;而不写明文。 这样即便 application.yml 被提交到 Git&…

Nginx 反向代理与负载均衡架构

一、反向代理基础 实验目的&#xff1a;通过 Nginx 反向代理&#xff0c;将客户端请求按类型&#xff08;静态页面 / 动态 PHP 页面&#xff09;转发到不同的后端服务器&#xff08;RS1 处理静态资源&#xff0c;RS2 处理动态请求&#xff09;&#xff0c;实现 “客户端只与代…

【Mybatis入门】配置Mybatis(IDEA)

Mybatis和JDBC一样&#xff0c;是连接数据库的工具。它是一款优秀的持久层框架&#xff0c;主要用于 Java 语言中简化数据库操作&#xff0c;实现对象与数据库表之间的映射。Mybatis相比于JDBC的优势Mybatis消除了传统 JDBC 代码中繁琐的手动处理、参数设置、结果集解析等重复工…

多路转接之epoll 【接口】【细节问题】【LT与ET模式】【Reactor】

目录 一.接口 1.1epoll_creaet 1.2epoll_ctl 1.3epoll_wait 二.细节问题 2.1 工作原理 2.2 epoll的demo 2.3 epoll的优点 三. LT 与 ET模式 理解ET 四. reactor 一.接口 1.1epoll_creaet 注意返回值是一个文件描述符 创建一个epoll模型 1.2epoll_ctl 返回值&…

渗透测试现已成为 CISO 战略的核心

随着数字供应链的扩展以及生成式人工智能在关键系统中的嵌入&#xff0c;安全领导者正在重新思考其网络安全策略。Emerald Research 最近对 225 位安全领导者进行的一项调查发现&#xff0c;68% 的人担心第三方软件和组件带来的风险。虽然大多数受访者表示他们正在满足监管要求…

音视频学习(五十三):音频重采样

概述 音频重采样&#xff08;sample rate conversion, SRC&#xff09;是把采样率从 Fs_in 变换为 Fs_out 的过程。常见场景有格式转换&#xff08;44.1→48 kHz&#xff09;、采样率匹配&#xff08;播放链路统一采样率&#xff09;、以及通信中语音采样率升降&#xff08;8 k…

【C#】正则表达式

一、核心优势&#xff1a;用一小段规则搞定大量复杂的字符串匹配&#xff0c;查找和替换&#xff0c;并且可移植可复用。使用正则表达式的好处&#xff1a;1. 强大且灵活&#xff1a;可以一次性匹配非常复杂的规则&#xff0c;比如验证邮箱、提取特定的格式日志、解析URL&#…

【[特殊字符][特殊字符] 协变与逆变:用“动物收容所”讲清楚 PHP 类型的“灵活继承”】

你有没有遇到过这样的问题&#xff1a;“为什么子类方法可以返回 Cat&#xff0c;而父类只写了返回 Animal&#xff1f;” “为什么参数反而能从 CatFood 变成更宽泛的 Food&#xff1f;”这些看似“违反直觉”的设计&#xff0c;其实背后有一个优雅的编程概念&#xff1a;协变…

cesium/resium 修改子模型材质

我是 www.v2ex.com/t/1151549 的作者&#xff0c;在csdn这边补全一些更多的信息 相关工具 主项目插件版本&#xff1a; "cesium": "^1.131.0",、"resium": "^1.19.0-beta.1"、"three": "^0.178.0"、"react…

nvm install 14.21.3 时npm 无法下载和识别

错误&#xff1a;C:\Users\H3C>nvm install 14.21.3 Downloading node.js version 14.21.3 (64-bit)... Complete Downloading npm... Creating C:\Users\H3C\AppData\Local\Temp\nvm-install-939491942\temp Downloading npm version 6.14.18... Error while downloading h…

【网络运维】Linux:LNMP 项目实践

LNMP 项目实践 简介&#xff1a;什么是 LAMP/LNMP LAMP&#xff1a;LinuxApacheMysql/MariadbPHP/Python/Perl。 LNMP&#xff1a;LinuxNginxMysql/MariadbPHP/Python/Perl。 Linux&#xff1a;操作系统&#xff0c;提供程序运行基础。Apache/Nginx&#xff1a;Web 服务器&…

用 Docker 安装并启动 MySQL:从零到实战的完整指南

用 Docker 安装并启动 MySQL&#xff1a;从零到实战的完整指南MySQL 是目前最流行的关系型数据库之一&#xff0c;广泛应用于各类应用系统中。使用 Docker 部署 MySQL 可以极大简化环境配置&#xff0c;保证开发、测试和生产环境的一致性。本文将详细介绍如何使用 Docker 安装、…

动态规划----1.爬楼梯

70. 爬楼梯 - 力扣&#xff08;LeetCode&#xff09; /** 1阶:1步,即1种; 2阶:1步1步或直接2步,即2种 f(1) 1,f(2) 2 3阶:由1阶迈2步,或2阶迈一步; 4阶:由2阶迈2步,或3阶1步; n阶:由n-2阶迈2步,或n-1阶迈1步 f(n) f(n - 1) f(n - 2) */ class Solution {/**1阶:1步,即1种…