一个app多主题架构完全分析

ScoopsDemo

多主题风格代码demo

本文属代码GG原创,非经本人同意,禁止转载。

需要交流,联系微信:code_gg_boy

更多精彩,时时关注微信公众号code_gg_home

基本用法

  • 简要说明

    Scoops是一个android应用库,主要解决的是多主题实现方案。通过配置多个R.style.Theme ,代码进行动态设置主题,重启当前界面实现。

  • 原理分析

    主要通过设置主题(存储设置值), 重启activity,通过setTheme方式设置style实现。

  • 使用方法

1项目的build.gradle里面

2 模块的build.gradle里面

3 values里面加入themes.xml

配置一些主题,为了多主题更换使用

4 AndroidManifest.xml里面

配置上默认主题,这里要注意的是配置的和5里面写的默认的那个要一致

5 MainApp里面

完成初始化,主要设置一系列的主题。其中addToppings为的是注释的时候使用,后面会讲它的用法。setSharedPreferences 配置默认的存储key值addDayNightFlavor 设置DayNight的主题风格,这个随后会讲到。

6 在MainAcitvity里面

1:需要继承AppCompatActivity

2:需要在setContentView前面调用Scoop.getInstance().apply(this);将主题设置进来。

3:这里说下为什么需要在AndroidManifest.xml里面配置默认主题,因为Scoops设计,在判断主题没有更改的情况下,不进行设置主题,因此第一次进来不会设置。所以我们要配置默认主题。并且和MainApp里面设置的默认值一样。

这里的true第三个参数说明设置为默认主题,和我们在AndroidManifest.xml设置的主题一致即可。

7 效果如下

8 代码地址

官网 地址 https://github.com/52inc/Scoops

demo地址   https://github.com/luxiaoming/ScoopsDemo

注解用法

  • 简要说明

通过注释方式,完成多主题的效果更换。可以减少一些代码,使得代码更清晰一些。

  • 使用说明

1 首先写一个注释类

2 在MainApp

初始化的时候,将注释通过addToppings方式设置进去

3 在MainActivity

使用注释@BindToppingStatus 标记下状态栏的颜色跟随

使用注释@BindTopping 标记下某个控件的颜色跟随

@BindTopping标记里面还可以有参数

1 value对应Toppings里面的某个值

2 adapter 跟上一个适配器,主要是为了实现某些控件自定义的设置颜色方案

3 interpolator 可以配置颜色切换过程效果,比如AccelerateInterpolator.class

代码可以看到还有一个注释,叫 @BindView(R.id.fab) 这个就是之前讲的Butter Knife ,不了解的可以在文章末尾看到地址

具体效果如下

4使用

在ButterKnife.bind(this);绑定了界面view后,使用 Scoop.sugarCone().bind(this);将view ,适配器和动画切换效果设置进来

在需要更新颜色的地方,使用Scoop.sugarCone().update即可,参数为第一个值为更新的注释类型,比如Toppings.PRIMARY_DARK参数二为颜色值。

5 ColorAdapter适配器

如果需要自己自定义主题更换后的view颜色变换动作(主要是有时候不符合我们的需求,比如我们想动态改文本颜色,高亮色等),我们就需要自定义一个实现ColorAdapter的类,比如ButtonColorAdapter接口 ColorAdapter定义了两个方法

设置新的颜色值

void applyColor(T view, @ColorInt int color);

获取当前颜色值

int getColor(T view);

6 主题bug

1 使用 @BindTopping 注释的时候,必须加上adapter=XXX.class 如果用默认的 ,请加上adapter = DefaultColorAdapter.class

2 默认的设置ScoopSettingsActivity界面,当设置为默认主题的时候,会出现bug。原因是这个界面指定了主题android:theme=”@style/Theme.AppCompat.Light” 如果我们默认的界面指定的跟这个不一样,则这个设置界面则会在默认主题的时候出错,和设置的效果不一致。解决方案:自己写一个设置界面呗。

7 demo地址

https://github.com/luxiaoming/ScoopsDemo

Butter Knife 注释编程阅读地址:

http://mp.weixin.qq.com/s?__biz=MzI1MjMyOTU2Ng==&mid=2247483660&idx=1&sn=9fc37fdb8f84763896b2696c03070db0&scene=4#wechat_redirect

白天夜间主题

很多应用都有这个功能,可以选择白天和夜间模式,给用户更好的体验。为此,系统也提供了一种机制,来实现此功能。

模式主要分为四种 夜间 白天 跟随系统 和自动。具体实现可以去看com.android.support:appcompat-v7:23.0.0源码

夜间和白天模式很好理解。自动就是根据时间判断是否为白天和夜间,自动选择对应主题。跟随系统则使用系统的值,依赖系统。

实现原理

通过两组主题,分别放在values和values-night下面,系统根据你设置的模式,对应的去找主题配置值,然后设置上去即可。

使用说明

不使用Scoops方式

1自定义一个属性Attrs.xml

这里可以看到定义了两个属性textColor和textSize 格式分别为color和dimension

2创建一个目录values-night

3在values和values-night下面

新建一个文件themes.xml,同时配置相同的主题,加入我们自定义的属性textColor,给它配置值。

values下的属性

values-night下的属性

4使用的地方

这里mMode的值可以取以下几个

MODE_NIGHT_FOLLOW_SYSTEM

MODE_NIGHT_YES

MODE_NIGHT_NO

MODE_NIGHT_AUTO

5我们配置下使用的地方

这里的 android:textColor=”?attr/textColor” 记住用的是?attr来使用自定义的属性

6具体的结果,看Primary Color颜色变化

7代码地址

https://github.com/luxiaoming/ScoopsDemo

使用Scoops方式

1:MainApp

使用addDayNightFlavor将一个主题设置为DayNight模式

2:在对应的主题里面配置上文本颜色

values里面

values-night里面

3:进入app,在设置里面设置成dayNight模式后,点击按钮Scoops方式查看效果即可。

4:效果如下

5:代码地址

https://github.com/luxiaoming/ScoopsDemo

原理分析

核心代码位置

https://github.com/52inc/Scoops/tree/master/scoops/src/main/java/com/ftinc/scoop可以看到主要文件

Flavor.java 存储每个主题信息

Scoop.java 主文件,主要提供接口,作为对外调用。

SugarCone.java 解析注释的主文件,通过使用bind方法,去反射找到编译出来的Toppings类,通过这个来关联上来。

Topping.java 自定义注释方法。标记在属性上面,然后通过编译时候,使用插件scoops-compiler,生成后缀为Toppings的绑定类,随后我们使用bind函数,将这些类和界面关联起来。

关键方法

Scoop.apply函数

我们来看下public void apply(Activity activity)的具体代码流程找到当前的主题getCurrentFlavor

判断主题是否是白天夜间模式,如果是,设置模式然后使用

另一个apply方法,参数是activity和主题id设置主题,找到设置的背景色,设置窗体背景,然后返回去,我们自己recreate 重新启动当前界面,实现切换。

编译插件

https://github.com/52inc/Scoops/tree/master/scoops-compiler

主要目的是解析我们自定义的注解。解析的主要是我们在初始化时候使用addToppings加入的我们的注解。找到后,解析出来注解的标记值,切换过场特效,和适配器。标记值的目的是更新值的时候,用这个来做区分。

代码逻辑:找到所有的绑定在这个标记的view,然后逐个调用对应的适配器,进行对应的颜色更新。我们来看下核心的bind函数

我们看下bind 代码,主要看下getViewBinder这个方法即可。继续去看findViewBinderForClass 函数

代码主要流程为:从缓存能找到,直接返回。找不到,然后查找Class.forName(clsName + “_ToppingBinder”)类,构造一个,然后将这个返回,并缓存下来。然后调用里面的bind进行关联view我们反编译可以看到MainActivity_ToppingBinder.smali这个smali文件,这个就是插件生成出来的代码。我们反编译下,看下这个文件做了什么。

看到了吧,将注释的全部归类进来,为后面更新的时候查找使用。注释的原理就是如此了。

时间: 2024-10-10 18:16:00

一个app多主题架构完全分析的相关文章

一个App架构例子分析--使用MVP模式;使用Otto实现模块通信

一.这个App整体的架构划分: 分为四大模块: 1.app模块 2.common模块 3.domain模块 4.model模块 app模块的依赖: dependencies {     compile fileTree(dir: 'libs', include: ['*.jar'])     compile project(':domain') ... } 它依赖domain,领域层模块.在app模块中,应用了MVP模式,把一个activity中的View和Presenter划分掉. domai

iOS应用架构现状分析

iOS从2007年诞生至今已有近10年的历史,10年的时间对iOS技术圈来说足够产生相当可观的沉淀,尤其这几年的技术分享氛围无论国内国外都显得异常活跃.本文就iOS架构这一主题,结合开发圈里讨论较多的几种主流方式,再配以博主自己的理解,做下现状分析.给自己做下知识梳理的同时,也期望能引入新的思考. 架构的定义 过去6年多几乎绝大部分时间都浸淫在iOS平台,翻阅过不少关于架构的文章,发现众人对架构的理解颇有些差异,总体来说可分为四类: 第一类:精简型应用架构 这类架构的文章分析主要还是围绕MVC展

Android App的设计架构:MVC,MVP,MVVM与架构经验谈

来源: Android App的设计架构:MVC,MVP,MVVM与架构经验谈 和MVC框架模式一样,Model模型处理数据代码不变在Android的App开发中,很多人经常会头疼于App的架构如何设计: 我的App需要应用这些设计架构吗? MVC,MVP等架构讲的是什么?区别是什么? 本文就来带你分析一下这几个架构的特性,优缺点,以及App架构设计中应该注意的问题. 1.架构设计的目的 通过设计使程序模块化,做到模块内部的高聚合和模块之间的低耦合.这样做的好处是使得程序在开发的过程中,开发人员

做一个App究竟要花多少钱?

作为互联网从业者,被外行的朋友们问及最多的问题是: “做一个网站需要多少钱?”或者“做一个APP需要多少钱?”. 作为做过完整网站项目和APP的人,今天从产品经理的角度,一起来算一下中小型APP从无到有需要做哪些工作,以及为达成使命,需要付出多少金钱代价. 以下内容的前提是: 深圳.移动互联网方向.包含研发一个新产品过程中一些常见的工作,并非十全十美. 首先假设在做APP之前我们已经有了一个成熟的团队(这是非常幸运的前提,很多产品研发进度极其缓慢的原因之一就是在过程中不断在招人),团队的结构以架

新闻APP后端系统架构成长之路

前言:一年来从接受APP后端工作到现在可谓一路艰辛,中间踏过无数坑坑洼洼,也从中学到很多很多,之前领导也多次提醒,平时多总结.把经验形成系统,但平时大部分时间一直在忙于开发.处理问题,天天马不停蹄的往前走.眼看着春节将至,16年又过去了,业务有了很大发展,我们系统也愈加完善.之前一直也没有时间静下心来后头看看,眼下随着6.0版本开发上线完毕,稍得片刻喘息,自己也想想,也是时候回头看看.总结一下了. 1,初入圣地 2,筑基:完全重构 3,金丹:踩坑..而且是踩大坑 4,元婴:面临挑战,流量来袭 5

如何使用viewpager与fragment写一个app导航activity

今天我们来看一下如何使用viewpager和fragment组合来写一个app导航activity,这里使用到了android开源控件viewpagerindicator,有兴趣的同学可以去它网站上看看它的介绍. 附上效果截图一张: demo中只有一个activity,是用activity_main.xml来布局,其内容如下: <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:and

【转】微信、陌陌 架构方案分析

来源:http://www.wubiao.info/401 作者:wubiao 微信.陌陌 架构方案分析 近两年.手机应用.莫过于微信.陌陌之类最受欢迎.但实现原理,分享文章甚少. 故,提出两种方案,供分享:不正确之处.敬请留言学习. 目标 解决大型应用(微信.陌陌级别)中.用户经纬度在不断更新.用户查找频繁的问题. (每分钟1000W级) ==============================================================================

实现键值对存储(三):Kyoto Cabinet 和LevelDB的架构比较分析

译自  Emmanuel Goossaert (CodeCapsule.com) 在本文中,我将会逐组件地把Kyoto Cabinet 和 LevelDB的架构过一遍.目标和本系列第二部分讲的差不多,通过分析现有键值对存储的架构来思考我应该如何建立我自己键值对存储的架构.本文将包括: 1. 本架构分析的意图和方法 2. 键值对存储组件概览 3. Kyoto Cabinet 和LevelDB在结构和概念上的分析 3.1 用Doxygen建立代码地图 3.2 整体架构 3.3 接口 3.4 参数化

移动App服务端架构设计

移动App服务端架构设计 我从事手机app服务端开发现在已经是3个年头,自己也整理出了一套相对好用的服务架构,写出来,跟大家一起分享.如有不足,还请多指教. 一:基础流程图. 其实有一点还需要加上,就是对json的压缩和加密,一来给用户节约流量,二来防止请求被截取破解我们的参数.具体先压缩后加密还是先加密后压缩这个问题看需求. 看到这个架构设计时,你们可能会说如果程序入口挂了,所有的服务都不可以用了. 所以这个架构的弱点在程序入口处,因此要有一(多)台机器做负载,负载的工具可以是HaProxy(