android 皮肤方案,Android开发:试一下另类的主题色无缝切换方案——Databinding下实现控件皮肤无缝切换...

目前仅作为探讨尝试方案,未经足够的测试进行校验,慎用!!

无缝切换主题色

这个功能一直都是Android的开发经常遇到的。我逛的最多的B站App就是一个很好地例子,他们的皮肤切换是无缝的,那我们自己能不能自己也来搞一个,当然是可以的,虽然有重复造轮子,但是我们还是需要不断锻炼自己的开发水平,尝试不同的方案。

Github可以找到一个不错的皮肤切换库:Android-Skin-Loader

基于LayoutInflaterFactory的皮肤切换,涉及到LayoutInflater 里setFactory(LayoutInflater.Factory factory)和setFactory2(LayoutInflater.Factory2 factory) 的知识点,这里不展开。

看完这个库的源码我想了个问题,我能不能另外开辟一条简单的路去走呢,这时候捡起了手中的Databinding。

所以本文章是基于Databinding下进行的,受限于框架使用,所以相比于Android-Skin-Loader,我建议使用Android-Skin-Loader因为它更加灵活

本文章提到的方案有限制了,特别是不支持Databinding的项目,诸如在旧项目上迭代的不适用本方案,不喜欢Databinding框架的同学也不太适用,因为有很多模板代码,而且是用Kotlin进行开发的,如果不想因为尝试该方案而项目引入额外的Kotlin也不适用。

先介绍

本库的测试环境是基于我一个玩安卓项目进行的:github.com/ShowMeThe/M…

本库地址,可单独拷贝skinlib的内容:github.com/ShowMeThe/S…

Gif如下:7e47d58799530f00ea3110095c5a246b.gif

在Application初始化

val themes_name = arrayListOf("BlueTheme","RedTheme","PurpleTheme","OrangeTheme","YellowTheme")

SkinManager.init(this).addStyle(

themes_name[0] to R.style.MaterialTheme_Blue,

themes_name[1] to R.style.MaterialTheme_Red,

themes_name[2] to R.style.MaterialTheme_Purple)

.build()

SkinManager.getInstant().setOnStyleChangeListener {

//主题切换的监听

}

//设置当前主题,不设置会默认拿了addStyle里面的第一个index,即index是0那个设置

SkinManager.currentStyle = ""

复制代码

分别配置主题的名字Key和对应的Value,Value是Style里面对应的资源

@color/colorAccent

@color/colorAccent

@drawable/shape_drawer_head_bg

@color/color_5f4fc3f7

@color/colorAccent

@color/colorAccent

@color/colorAccent

@color/colorAccent

@color/colorAccent

@color/colorAccent

@color/colorAccent

@color/colorAccent

@drawable/shape_blue_cursor

@color/colorAccent

@color/colorAccent

@color/colorAccent

复制代码

同时增加对Json的解析,因为不是所有的主题都要写在style,可能遇到需要后台下载解析的情况

val json = AssetFile.getJson(this,"orange.json")

val colorEntity = json.fromJson()

复制代码

其中getJson方法如下:

fun getJson(context: Context, fileName: String): String {

val stringBuilder = StringBuilder()

try {

val assetManager = context.assets

val bf = BufferedReader(InputStreamReader(assetManager.open(fileName)))

var line: String

bf.use {

while (true) {

line = bf.readLine() ?:break

stringBuilder.append(line)

}

}

} catch (e: IOException) {

e.printStackTrace()

}

return stringBuilder.toString()

}

复制代码

fromJson方法入下

inline fun String?.fromJson(): T? {

if (isNullOrEmpty()) { //判断空和null

return null

}

return try {

val clazz = T::class.java

gson.fromJson(this, clazz) //Gson解析

} catch (e: JsonSyntaxException) {

e.printStackTrace()

null

}

}

复制代码

这两个方法各位可以自己写,我这里提供参考而已

由于当时写的时候,路开窄了而且不想引入太多额外的库,对Widget判断是直接采用包名的提取,所以只支持AndroidX和官方那个MaterialDesign的Widget库

于是添加了一个自定义插件的方法IPlugin,举SwipeRefreshLayout这个Widget作为例子:

class RefreshPlugin : IPlugin {

//对应style的

override fun individuate(view: SwipeRefreshLayout, attrName: String) {

when (attrName) {

themes_name[0] -> view.setColorSchemeResources(R.color.colorAccent)

themes_name[1] -> view.setColorSchemeResources(R.color.color_304ffe)

themes_name[2] -> view.setColorSchemeResources(R.color.color_6200ea)

}

}

// 对应Json参数,colors对应Json中colorObjects字段

override fun individuate(

view: SwipeRefreshLayout,

attrName: String,

colors: ArrayList?

) {

}

}

}

复制代码

这个Json对应

{

"theme_viewGroup_background": "FBC02D",

"theme_viewGroup_backgroundColor": "FBC02D",

"theme_card_strokeColor": "FBC02D",

"theme_text_color": "FBC02D",

"theme_button_textColor": "FBC02D",

"theme_button_rippleColor": "2cFDD835",

"theme_button_iconTint": "FBC02D",

"theme_button_strokeColor": "FBC02D",

"theme_bottom_navigation_iconTint": "FBC02D",

"theme_bottom_navigation_textColor": "FBC02D",

"theme_imageView_tint": "FBC02D",

"theme_floating_backgroundColor": "FBC02D",

"theme_edit_cursorDrawable": "FBC02D",

"theme_edit_highlightColor": "FBC02D",

"theme_inputLayout_boxColor": "FBC02D",

"theme_inputLayout_hintColor": "FBC02D",

"colorObjects": [

"FBC02D",

"2cFDD835"

]

}

复制代码

总结

该库基于Kotlin + DataBinding下可以在布局文件xml里使用 @BindAdapter 的注释的拓展函数,再利用对应的key去遍历寻找不同类型view的对应设置属性,由于存在大量遍历,会有性能问题,总体上性能是个缺陷,而且如果项目存在大量的自定义布局或者大量的图片的画,很难进行这种纯色的替换,所以这里只是做一个小小尝试,毕竟要尝试嘛!不尝试,怎么知道结果呢

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值