专栏名称: 开发者全社区
分享和推送Java/Android方向的技术和文章,让你成为这方面的大牛,让你每天都成长一点。同时,我们也会邀请BAT的大牛分享原创!
目录
相关文章推荐
郭霖  ·  一篇文章带你彻底掌握Optional ·  3 天前  
郭霖  ·  音视频基础能力之 Android ... ·  4 天前  
郭霖  ·  Android - 监听网络状态 ·  1 周前  
51好读  ›  专栏  ›  开发者全社区

Prism(棱镜)——一款优秀的Android 主题动态切换框架

开发者全社区  · 公众号  · android  · 2017-05-07 09:01

正文

相关阅读:

吊炸天!74款APP完整源码!

Android 自定义录音、播放动画View,让你的录音浪起来

GitHub上star超过2k的安卓项目和代码风格指南(绝对干货)

Prism(棱镜) 是一个全新的 Android 动态主题切换框架,虽然是头一次发布,但它所具备的基础功能已经足够强大了!本文介绍了 Prism 的各种用法,希望对你会有所帮助,你也可以对它进行扩展,来满足开发需求。

先说一下 Prism 的诞生背景。其实我没打算一上来就写个框架出来,当时在给 Styling Android 博客写一些使用 ViewPager 来实现 UI 动态着色的系列文章,文中用到的代码被我重构成适合讲解用的组件,然后我发现这些代码可以整理成一个简洁的 API,于是乎便有了做 Prism 框架的想法。我把 Prism 拿给我比较认可的几个人看,他们都觉得不错,这样我就一点点把它做成了库。经过反复使用,我觉得这个 API 在保持架构简洁的同时已经具备了很多的功能,就决定把它发布出来了跟大家分享。

Prism 分为三个独立库:

  • prism 是 Prism 的核心库

  • prism-viewpager 实现了 ViewPager 与核心库的对接

  • prism-palette 实现了 Palette 调色板与核心库的对接

目前已发布的版本是 1.0.1,最新版本的链接是https://bintray.com/stylingandroid/maven/prism/_latestVersion

添加好必要的依赖就可以使用 Prism 了。

Prism 基本上由三种对象类型构成:SetterFilter 和 Trigger

Setter 用来设置 UI 对象的颜色,一般是 View 但也可以是其他元素,后面会讲到。它的基本用法是将 setColour(int colour)(或 setColor(int color))映射到 View 封装的某个方法上。例如,内置的 ViewBackgroundSetter 会映射到 setBackgroundCOLOR(int color) 上。有时 Setter 在不同版本的 Android 上会产生不同的效果,例如 StatusBarSetter 在 Android Lollipop (5.0) 之前的系统上不起作用,因为 Lollipop 之前的版本不支持改变 StatusBar 的颜色。不过 Prism 会随机应变,不会引起程序崩溃,请放心使用,一切交由 Setter 搞定。

Prism 内置有如下几个基本的 Setter:

  • FabSetter(FloatingActionButton fab)
    为 Android Design Support Library 中的 FloatingActionButton(简写 FAB)设置背景色。

  • StatusBarSetter(Window window)
    设置指定窗体的状态栏颜色,注意它的操作对象并不是 View。

  • TextSetter(TextView textView)
    设置 TextView 中的文本颜色。

  • ViewBackgroundSetter(View view)
    设置 View 的背景颜色。

当然,你也可以创建新的 Setter 给自定义 View 中的不同组件设置颜色,或者给同一个 View 创建多个 Setter 来设置不同的属性,同时对不同组件进行着色。只要把自定义的 Setter 添加到 Prism 中即可生效。

Filter 可以对颜色进行转化处理。一般向 Prism 传入的是一个颜色值,有时我们可能需要把该颜色的不同色度应用到不同的 UI 组件上,这时要用 Filter 将颜色进行一下转换再输出。内置的基本 Filter 有:

  • IdentifyFilter()
    返回与输入相同的颜色。

  • ShadeFilter(float amount)
    将输入颜色与黑色混合进行加深处理。amount 为 0 到 1 之间的浮点数,代表黑色的混合比率。当 amount 为 0 时,输出颜色就是输入颜色;为 1 时,则输出纯黑色。

  • TintFilter(float amount)
    将输入颜色与白色混合进行加亮处理。amount 为 0 到 1 之间的浮点数,代表白色的混合比率。当 amount 为 0 时,输出颜色就是输入颜色;为 1 时,则输出纯白色。

Trigger 是颜色变化时所触发的事件。通常它会调用 Prism 实例上的 setColour(int colour),将颜色变化的消息传递给在该实例上注册过的所有 Setter 方法。

因为 Trigger 需要额外的依赖库,所以 Prism 核心库没有将它包含进去,但在 ViewPager 和 Palette 的扩展库中都有提供。

上面的代码大部分都是基本的 Android 开发操作,不需要特别的解释。重点看一下创建 Prism 实例的部分——先创建一个将输入颜色加亮 50% 的 Filter(TintFilter),然后创建 Prism.Builder 实例,并添加 AppBar 实例(这会为 AppBar 创建一个 Setter 来设置背景色)、Window(为 StatusBarColour 创建 Setter 来设置状态栏颜色)、TextView(使用 text(TextView) 来设置文字颜色),以及 FloatingActionButton(设置 FAB 背景色并应用第一步中的 TintFilter)。最后用build() 来完成 Prism 实例的构建。

现在所有组件都被串联了起来,此时只要调用该实例上的 setColour(int colour) 就可以同时改变这些组件的颜色:

  1. prism.setColour(0xFF0000);

代码最后明确使用了 onDestroy() 来清除 Prism 实例。其实严格来说这一步并不是必须要有,因为等到 Activity 被清除后,系统不会保留对 Prism 实例的引用,垃圾回收器会将 Prism 实例处理掉。不过如果后面真不会再用的话,及时做下手工清理也无妨。

Prism 的基本用法就是这样,只要在 onCreate() 中增加六行代码,就能同时改变各组件的颜色(下面使用了 FloatingActionButton 来触发颜色切换)。


把 Setter 和 Filter 配合起来使用省去了大量的样板代码,让事情简单好多,实际上它们完成的工作并不复杂,但如果搭配 Trigger 使用,情况就不一样了。

首先将 prism-viewpager 做为依赖添加到项目中来,对应的 build.gradle 内容如下:

Trigger 是 Prism 实例最前方的关卡,它来触发主题颜色的改变。我们先来看一下 ViewPagerTrigger 如何根据用户操作来触发 ViewPager 改变颜色。ViewPager 的 Adaptor 要为每个页面位置提供颜色信息,这需要通过 ColourProvider 接口来完成(或 ColorProvider,如果不介意使用这种拼写方式所带来的少许性能损失的话 1):


如果你用过 PagerTitleStrip 或 Design Library 中的 TabLayout,那对给每个页面位置提供一个标题的做法就不陌生了。ColourProvider 接口就是这个作用,只不过它把标题的字符串换成了 RGB 颜色值。Adapter 已内置了 getCount() 方法,所以在继承 Adapter 时不用重新定义这个方法,可以按下面的示例来实现自己的 Adaptor:

我们得到了一个实现了 ColourProvider 接口的 Adaptor,现在可以把它跟 ViewPagerTrigger 一起使用了:


在 setupViewPager() 中,我们先创建了一个 RainbowPagerAdapter 实例,并把它应用到 ViewPager 上,然后又创建了一个加亮 FAB 背景色的 TintFilter, 以及与 ViewPager 和 Adaptor 相关联的 Trigger。

接着以同样的方式再创建一个 Prism 实例,这次我们为 Prism 绑定了更多的组件,并添加了刚才做好的 Trigger。你可能注意到 ViewPager 实例被设置了颜色,这会改变 ViewPager 滑动到边界时产生的发光效果的颜色(因为不同版本的系统会用不同的方式来处理发光效果,但 Prism 内部会处理好这些差异)。

然后把 TabLayout 和 ViewPager 进行绑定(TabLayout 要求这样做,但 Prism 并不需要这样),最后把 ViewPager 的初始页面设为第一页。好了大功告成,现在主题色会随着标签页的切换而改变,请看 Demo:


细心的人可能会发现其间的颜色过渡看起来并不生硬,颜色是随着用户的拖拽而逐渐产生变化:

还有一些更微妙的细节。如果用户选择了间隔很远的标签页面,正常情况会过渡显示从开始到结束标签之间的每种颜色,从视觉上说会略显唐突和不自然,而 ViewPagerTrigger 只选择开始和结束标签的两种颜色来做平滑过渡(也就是黄色 YELLOW 和紫色 VIOLET,跳过 GREEN、BLUE 和 INDIGO):


这是 ViewPager 滑动到边界时的动画效果:

最后我们来说一下 prism-palette 的用法。先将它做为依赖添加到项目中来,对应的 build.gradle 内容如下:

PaletteTrigger 使用起来非常简单,只要创建一个 PaletteTrigger 实例,再把它添加到 Prism.Builder 上:

接下来,我们可以通过调用 PaletteTrigger 的 setBitmap(Bitmap bitmap) 方法来触发颜色变化。这会创建一个新的 Palette 实例,等到 Palette 从图像中提取完色样后就去触发 Prism。

要想正确地为相关联的 UI 组件着色,我们需要了解 Palette 的工作原理。

Palette 可以从一张图片中提取出最多 6 种不同的色样:

  • 鲜艳

  • 鲜艳浓

  • 鲜艳淡

  • 柔色

  • 柔色浓

  • 柔色淡

每种色样又可以分离出 3 种色值:

  1. Filter darkVibrantTitle = paletteTrigger.getDarkVibrantFilter(paletteTrigger.getTextFilter());

在上面的示例中我们实际并没绑定 UI,只是演示一下怎样提取各种色样以及如何应用。但根据前面讲过的内容,相信加入绑定也不是难事。

【重要提示】由于代码版权问题,Prism 的开发计划已无限期搁置,具体说明请参考 Prism 源码仓库中的 README 内容。之所以仍然要发布这篇文章,是想让大家了解到 Prism 现有的功能,对自己的开发有所帮助。

原文链接:

Prism Fundamentals – Part 1

Prism Fundamentals – Part 2

Prism Fundamentals – Part 3


转载自:https://blog.leancloud.cn/3612/

看完本文有收获?请分享给更多人


Java和Android架构

欢迎关注我们,一起讨论技术,扫描和长按下方的二维码可快速关注我们。搜索微信公众号:JANiubility。

公众号:JANiubility