Google提供的更换主题包方法参考:

https://source.android.google.cn/devices/architecture/rros?hl=zh-cn
https://www.jianshu.com/p/398f1beb1a6e
https://blog.csdn.net/dayong198866/article/details/106281654

主题语言切换

1.开发环境:Android studio 3.4.0,kotlin实现
2.开发准备
①在values中添加资源文件【“new“ → "Values resouce file”】定义为”custom_theme_attrs“,内容如下:

<?xml version="1.0" encoding="utf-8"?>
<resources><!-- 控制app背景色 format:颜色值、资源引用 --><attr name="custom_attr_app_bg" format="color|reference" /><!-- 控制app标题栏背景色 format:颜色值、资源引用 --><attr name="custom_attr_app_title_layout_bg" format="color|reference" /><!-- 用户头像显示占位Drawable format:颜色值、资源引用 --><attr name="custom_attr_user_photo_place_holder" format="color|reference" /><!-- 用户昵称字体颜色 format:颜色值、资源引用 --><attr name="custom_attr_nickname_text_color" format="color|reference" /><!-- 用户备注字体颜色 format:颜色值、资源引用 --><attr name="custom_attr_remark_text_color" format="color|reference" /><!-- 用户头像显示的透明度 format:尺寸值、资源引用 --><attr name="custom_attr_user_photo_alpha" format="dimension|reference" /><attr name="titlebar_bg" format="color|reference"/><attr name="titlebar_text_color" format="color|reference"/><attr name="body_bg" format="color|reference"/><attr name="body_text_color" format="color|reference"/><attr name="title" format="string"/>
</resources>

②在资源文件”styles“中添加如下代码【添加主题】

<!-- 主题:白天 --><style name="theme_day" parent="Theme.AppCompat.Light.NoActionBar"><item name="titlebar_bg">#1EABF0</item><item name="titlebar_text_color">#FFFFFF</item><item name="body_bg">#F3F3F3</item><item name="body_text_color">#333333</item></style><!-- 主题:夜晚 --><style name="theme_night" parent="Theme.AppCompat.Light.NoActionBar"><item name="titlebar_bg">#000000</item><item name="titlebar_text_color">#FFFFFF</item><item name="body_bg">#888888</item><item name="body_text_color">#EAEAEA</item></style><!-- theme_day.chi_sim 表示继承theme_day --><style name="theme_day.chi_sim"><item name="title">主题配置</item></style><style name="theme_night.eng"><item name="title">TopicConfig</item></style>

3.添加观察者接口:

package com.zjhj.maxapp.themeinterface ThemeChangeObserver {/*** 加载当前主题*/fun loadingCurrentTheme()/*** 主题改变后通知*/fun notifyThemeChanged()
}

4.在BaseActivity中实现接口

package com.zjhj.maxapp.baseimport android.content.Context
import android.os.Bundle
import android.view.WindowManager
import androidx.appcompat.app.AppCompatActivity
import com.zjhj.maxapp.App
import com.zjhj.maxapp.R
import com.zjhj.maxapp.theme.ThemeChangeObserver
import com.zjhj.maxapp.utils.L //自定义日志类/*** CreateTime 2020/4/2 09:10* Author LiuShiHua* Description:*/
abstract class BaseActivity : AppCompatActivity(), ThemeChangeObserver {private val KEY_THEME_TAG = "myThemeTag"private var isChangeTheme: Boolean = falseoverride fun onCreate(savedInstanceState: Bundle?) {window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)setThemeBeforeCreate()super.onCreate(savedInstanceState)setContentView()initView()initData()getData()}/***/private fun setThemeBeforeCreate() {App.registerObserver(this)//将当前Acitivity注册成观察者loadingCurrentTheme()}/*** 加载当前主题* 需要在super.onCreate(savedInstanceState)之前执行才会生效*/override fun loadingCurrentTheme() {when (getThemeTag()) {1 -> setTheme(R.style.theme_day_chi_sim)-1 -> setTheme(R.style.theme_night_eng)}L.d("loadingCurrentTheme:" + this::class.java)}abstract fun setContentView()abstract fun initView()abstract fun initData()abstract fun getData()/*** 获取当前主题类型*/protected open fun getThemeTag(): Int {val preferences = getSharedPreferences("MaxTheme", Context.MODE_PRIVATE)return preferences.getInt(KEY_THEME_TAG, 1)}/*** 设置主题类型* 保存在sharedprferences中*/protected open fun setThemeTag(tag: Int) {L.d("setThemeTag:" + tag)val preferences = getSharedPreferences("MaxTheme", Context.MODE_PRIVATE)val edit = preferences.edit()edit.putInt(KEY_THEME_TAG, tag)edit.commit()App.notifyByThemeChanged()}/*** 注销这个观察者*/override fun onDestroy() {App.unregisterObserver(this)super.onDestroy()}
}

5.在APP(继承 Application)中管理观察者

package com.zjhj.maxappimport android.app.Application
import android.content.Context
import com.zjhj.maxapp.theme.ThemeChangeObserver/*** CreateTime 2020/4/9 09:40* Author LiuShiHua* Description:*/
class App : Application() {companion object {//静态属性或方法lateinit var context: Contextgetprivate var mThemeChangeObserverStack: MutableList<ThemeChangeObserver>? = null/*** 获得observer堆栈*/private fun obtainThemeChangeObserverStack(): MutableList<ThemeChangeObserver>? {if (mThemeChangeObserverStack == null) mThemeChangeObserverStack = ArrayList()return mThemeChangeObserverStack}/*** 向堆栈中添加observer*/fun registerObserver(observer: ThemeChangeObserver?) {if (observer == null || obtainThemeChangeObserverStack()!!.contains(observer)) returnobtainThemeChangeObserverStack()!!.add(observer)}/*** 从堆栈中移除observer*/fun unregisterObserver(observer: ThemeChangeObserver?) {if (observer == null || !obtainThemeChangeObserverStack()!!.contains(observer)) returnobtainThemeChangeObserverStack()!!.remove(observer)}/*** 向堆栈中所有对象发送更新UI的指令*/fun notifyByThemeChanged() {val observers: List<ThemeChangeObserver>? = obtainThemeChangeObserverStack()for (observer in observers!!) {observer.loadingCurrentTheme() //observer.notifyThemeChanged() //}}}override fun onCreate() {super.onCreate()context = this}
}

5.在BaseActivity实例中去调用更换主题

package com.zjhj.maxappimport com.zjhj.maxapp.base.BaseActivity
import kotlinx.android.synthetic.main.activity_theme.*class ThemeActivity : BaseActivity() {override fun setContentView() {setContentView(R.layout.activity_theme)}override fun initView() {changeTheme.setOnClickListener {if (getThemeTag()==1) {//设置主题setThemeTag(-1)} else {setThemeTag(1)}recreate()//重新构建页面}}override fun initData() {}override fun getData() {}override fun notifyThemeChanged() {}
}

6.说明:网上有些建议是使用recreate()来重新构建页面就行,实际中很多Activity都无法使用recreate()来重新构建页面,或者想保存之前的页面信息而不希望页面重新构建,我这里使用的是在Activity中notifyThemeChanged中重新设置对应主题的属性值【感觉比较low】

...override fun notifyThemeChanged() {val typedValue = TypedValue()//获取当前主题下的titlebar_bg属性值,并赋给typedValuetheme.resolveAttribute(R.attr.titlebar_bg, typedValue, true)//设置属性值【注意:属性是那种类型,设置的时候就用成那种类型】toolBar.setBackgroundColor(typedValue.data)}
...

实现效果:在主题设置也改变主题后其他页面跟这变化

Android 主题切换(theme),语种切换,动态获取自定义属性(attr)值相关推荐

  1. android 主题xml,自定义Android主题风格theme.xml方法 Android开发技术

    自定义Android主题风格theme.xml方法 Android开发技术 2013 年 5 月 23 日 在Android中可以通过自定义主题风格方式来实现个性化以及复用,首先我们创建theme.x ...

  2. Android主题换肤 无缝切换

    作者 _SOLID 关注 2016.04.17 22:04* 字数 4291 阅读 23224评论 123喜欢 679 今天再给大家带来一篇干货. Android的主题换肤 ,可插件化提供皮肤包,无需 ...

  3. Android主题换肤 无缝切换 你值得拥有

    链接:https://www.jianshu.com/p/af7c0585dd5b 天再给大家带来一篇干货. Android的主题换肤 ,可插件化提供皮肤包,无需Activity的重启直接实现无缝切换 ...

  4. Android:主题(Theme)

    1.主题和样式的区别主要区别在 主题不能作用于单个View组建,主题应该对整个应用中的所有Activity起作用或者对指定的Activity起作用. 主题定义的格式应该是改变窗口的外观格式,例如窗口变 ...

  5. Android TextView 是否有省略号,动态获取和设置行数

    目录 前言 一.TextView设置最大行与省略号 二.检查文本是否省略 三.实战 前言 最近在做一个效果,就是当文本显示超出2行时,文本末尾出现...(省略号),并且显示一个[展开]的按钮.点击时[ ...

  6. 通过特性动态获取属性及值

    using System.Collections.Generic; using System.Data.SqlClient; using System.Data; using System; name ...

  7. JArray的使用以及动态获取对象属性值

    在使用c#引用using Newtonsoft.Json;以及using Newtonsoft.Json.Linq;时我们有可能遇见某些值无法直接从Jarray转为list集合,这时我们就需要使用Ja ...

  8. js获取自定义属性的值

    2019独角兽企业重金招聘Python工程师标准>>> <div id="v" value="123" data-url="黑 ...

  9. Android主题换肤实现

    本系列文章主要是对一个Material Design的APP的深度解析,主要包括以下内容 基于Material Design Support Library作为项目整体框架.对应博文:Android ...

最新文章

  1. Snmp扫描-snmpwalk、snmpcheck
  2. 【测试基础】测试用例的设计方法
  3. 注入eval,Function等系统函数,截获动态代码
  4. MongoDB常用操作总结
  5. Java 匿名存储过程_Java程序员的存储过程
  6. apache ignite_Kubernetes集群上的Apache Ignite和Spring第3部分:测试应用程序
  7. html5游戏开发box2djs,Box2D.js简易示例
  8. CSS 与 HTML5 响应式图片
  9. cad画流程图的插件_盘一盘,那些提效/创意的 vscode 插件
  10. 洛谷——P1296 奶牛的耳语
  11. [读书笔记]Linux命令行与shell编程读书笔记01
  12. nsis出错_cf nsis错误怎么办 nsis错误解决办法全解
  13. 利用Matlab进行图像处理
  14. ASP.NET入门基础教程查看
  15. Mac电脑如何添加打印机?
  16. ios 做不倒翁动画效果
  17. 万字说透 Decentraland:元宇宙的先行者
  18. yum -- Failed connect to mirrors.aliyuncs.com:80; No route to host
  19. 局域网助手_爱思助手“正品配件检测”功能使用方法
  20. 趋势操盘法则:资深操盘手6年60倍实战选股技法

热门文章

  1. 深度学习(1) ——图像分类
  2. Java基础项目——客户信息管理软件
  3. ps4移植android游戏,捡垃圾之路 篇八:这一次PSV用实力吊打Switch!2021你需要知道的安卓移植大作(含游戏下载)...
  4. 21:最大质因子序列
  5. 计算机换了显卡还是打不开,电脑配置可交换显卡打不开的解决办法
  6. CANalyzer/CANoe 回放CAN报文的流程
  7. 【Unity2D入门教程】简单制作战机弹幕射击游戏① 导入素材
  8. Matlab画动图并保存成gif之七——逐渐变大的透明球体+箭头
  9. VIVO X7玫瑰金与银色边框颜色区分 方案(C++实现)
  10. 分享:Guacamole 0.7.1 发布,基于Web的VNC客户端