前言
做程序开发,基础很重要。同样是拧螺丝人家拧出来的可以经久不坏,你拧出来的遇到点风浪就开始颤抖,可见基本功的重要性。此系列,专门收录一些看似基础,但是没那么简单的小细节,同时提供权威解决方案。喜欢的同志们点个赞就是对我最大的鼓励!先行谢过!
网上可能有一些其他文章,提供了解决方案,但是要么就是没有提供可运行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看上去就像是谷歌的实习生写的控件,兼容性做的有问题,虽然官方给出了两个属性解决问题,但是却没有对这两个属性做出贴切的解释说明。诶···算了,知道就行了,毕竟是大佬写的。欧了!
网友评论