时下热门的换肤框架,不管是Android-skin-support还是Android-Skin-Loader,亦或者是其它名为插件化、
无感知的换肤框架,无论说的有多么天花乱坠,其本质还是设置控件的background、src或者是textColor,实际上就是换背景(前景)图片或者背景/文字颜色。
这些基本都满足公司的业务需求
直到有一天我看到UI给的效果图上一个listview的滚动条也需要变颜色,what?这么细致的设计也是要点赞了。
看到这个需求后,第一反应是滚动条不属于listview的背景,所以没法用常规方法设置。
只能换种思路,因为皮肤框架有api可以直接获取到皮肤包里的色值,所以可以拿到这个色值设置到滚动条中。
那么问题就落在如何拿到滚动条并且设置它的背景色了。
首先,看下listView有没有直接拿到滚动条的方法。
很可惜,并没有直接getScrollBar()的方法,set也没有能直接设置scrollBar的背景方法:
看来可能谷歌觉得滚动条没必要订制化,就没有对外暴露api了,我们只能找到滚动条在具体哪个类里哪个属性再通过反射拿到它。
既然都要设置size了,肯定要先拿到scrollBar本身才行吧,点进去看到是一个get方法
继续点进去,OK,看到一个叫做mScrollCache的成员变量,其类型是ScrollabilityCache
再点进这个类,看看里面有什么。
ScrollabilityCache这个类是View里面的一个静态内部类,可以看到它有个ScrollBarDrawable类型的成员变量 scrollBar。这不就是我们要找的东西嘛,看见以Drawable结尾的后缀,顿时也放心了很多,基本上判定scrollBar是个drawable了,改颜色当然没问题了。
(Tips: 这里需要插一句,ScrollabilityCache是View的内部类,所以其实可以这么说,所有的view都有scrollBar,并不是ListView或者RecycleView独有的,最早先的时候我以为是listview里独有的,于是从listView里开始找scrollBar,结果一路找到View。。。它们之间的继承关系如下:ListView --> AbsListView --> AdapterView --> ViewGroup --> View)
为了证实scrollBar是个drawable的设想,我们继续向下看,但是这里ScrollBarDrawable是标红的,Android Studio中没法跳转,我们只有借助看源码神器 source Insight了(具体方法自行百度,反正很简单)。在source Insight找到这个类后,我们发现ScrollBarDrawable确实是继承Drawable的。
查看注释1,发现这个类添加了hide注解,说明这个类是隐藏的,没法通过API调用。只能通过反射调用了。
查看注释2,发现主要是这四个成员变量,横竖各两个,Track是滚动条的那个滑块,Thumb是滚动条的背景,我们通过反射拿到这几个成员变量再通过对应的setXXX方法去设置即可。
具体的实现代码如下(以垂直滚动条为例):
虽然我们文章切入点是关于换肤的,但是这些方法也很适合scrollBar的UI定制化。到这里,滚动条的故事基本就到此结束了。
不过我觉得可以再延展一下。
在项目中,经常会遇到不同的皮肤只是换个颜色,比如说类似下图的icon
它们颜色单一,内容简单,不同皮肤的区别只是颜色不一,这种情况完全就没必要做几套切图,只需要做一套默认的切图,然后通过drawable的setTint(Drawable drawable,int color)方法直接变色,方便很多。
你,Get到了吗?