相关阅读:
吊炸天!74款APP完整源码!
Android 自定义录音、播放动画View,让你的录音浪起来
GitHub上star超过2k的安卓项目和代码风格指南(绝对干货)
Prism(棱镜) 是一个全新的 Android 动态主题切换框架,虽然是头一次发布,但它所具备的基础功能已经足够强大了!本文介绍了 Prism 的各种用法,希望对你会有所帮助,你也可以对它进行扩展,来满足开发需求。
先说一下 Prism 的诞生背景。其实我没打算一上来就写个框架出来,当时在给 Styling Android 博客写一些使用 ViewPager 来实现 UI 动态着色的系列文章,文中用到的代码被我重构成适合讲解用的组件,然后我发现这些代码可以整理成一个简洁的 API,于是乎便有了做 Prism 框架的想法。我把 Prism 拿给我比较认可的几个人看,他们都觉得不错,这样我就一点点把它做成了库。经过反复使用,我觉得这个 API 在保持架构简洁的同时已经具备了很多的功能,就决定把它发布出来了跟大家分享。
Prism 分为三个独立库:
目前已发布的版本是 1.0.1,最新版本的链接是https://bintray.com/stylingandroid/maven/prism/_latestVersion。
添加好必要的依赖就可以使用 Prism 了。
Prism 基本上由三种对象类型构成:Setter、Filter 和 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)
就可以同时改变这些组件的颜色:
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 种色值:
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