谷歌大佬自带阴影圆角的CardView也有坑?!
前言
做程序开发,基础很重要。同样是拧螺丝人家拧出来的可以经久不坏,你拧出来的遇到点风浪就开始颤抖,可见基本功的重要性。此系列,专门收录一些看似基础,但是没那么简单的小细节,同时提供权威解决方案。喜欢的同志们点个赞就是对我最大的鼓励!先行谢过!
网上可能有一些其他文章,提供了解决方案,但是要么就是没有提供可运行demo
,要么就是demo不够纯粹
,让人探索起来受到其他代码因素的影响,无法专注于当前这个知识点(比如,我只是想了解Activity
的生命周期,你把生命周期探究的过程混入到一个很复杂的大杂烩Demo
中,让人一眼就没有了阅读Demo代码
的欲望),所以我觉得有必要做一个专题,用最纯粹
的方式展示一个坑
的解决方案.
先吐个槽
做开发的,少不了被UI大佬折磨的经历。之前做
阴影
的时候,都是自己绘制,太麻烦。后来直接让UI大佬给带阴影
的图片,大佬又不乐意。直到···发现谷歌居然提供了CardView
,不但带阴影
,还带圆角
? 喜出望外,但是,用过之后才发现还是有坑。不过好在有办法解决。CardView是 谷歌大佬按照android 自定义控件的规则写的控件,那我们作为高级 开(码)发(农),就有办法找到坑的原因并且,解决它的缺陷。
什么坑?
SDK 21以下SDK21以下.gif
但是在SDK 21(含21)以上:没有这种问题
SDK21(含)以上.gif.gif
确定是 兼容性问题。
查查刚才坑的原因
为什么加了圆角,在28的模拟器上效果OK,但是19的机器上有问题?直觉,就是在CardView的源码内部,在圆角的处理上,做了SDK版本的区分,而且19的处理貌似还没做好(大概这就是谷歌的实习生造的孽吧 囧)
查呗,啥原因,进源码看一眼。 发现:
image.png
image.png
image.png
image.png
image.png
同样都是利用拿到的radius
属性值,然后构建出一个Drawable
子类。但是 17以上21以下的处理是存在问题的。为何有问题,再进去看。
跟踪这个radius参数,
image.png
![]()
到了这里,发现radius被转化成了一个int值 mCornerRadius,继续跟踪
image.png
惊奇地发现,radius
居然影响到了CardView
的背景的padding
值?!
当addPaddingForCorners
为true
的时候,外部传入的radius
圆角值会参与padding
的计算。那么这个addPaddingForCorners
的值是哪来的?
一顿追踪之后(作为高级开(码)发(农),你一定可以追踪得到··所以我就省略了过程
),居然发现,
image.png
居然是CardView
的自定义属性cardPreventCornerOverlap
,可见这个值,在SDK 21以下的机器上运行,圆角角度参与到CardView的背景padding的计算中去。我们让它为false,不让他参与计算,就正常了。
坑2
居然还有第二个坑?
image.png
image.png
image.png
原因也是这个属性cardUseCompatPadding的影响,可以推测这个属性值,在21前后有对阴影和padding有不同的处理,原因可以按照上面的思路在去找一遍代码。
总之,要保持不同版本上UI效果一致,使用了阴影,就要写上cardUseCompatPadding=true
另:给出一个偏方,据说也能解决此问题,那就是创建value-v21目录,写一个同名的dimen值,手动给cardView加上间距,21以前为0(因为默认已经有间距了),21以后不为0.
总结
CardView看上去就像是谷歌的实习生写的控件,兼容性做的有问题,虽然官方给出了两个属性解决问题,但是却没有对这两个属性做出贴切的解释说明。诶···算了,知道就行了,毕竟是大佬写的。欧了!