今天在微博上看到Mr_Wrong丶同学提了个问题,问题指向了这里How to add a TextView above a FloatingActionButton in Android 。问题描述看下图,大致来说就是 FloatingActionButton
遮住了本该显示在上层的 TextView
。
下面有人给了解决方案,给 TextView
添加属性 android:elevation="7dp"
,乍一看,哇,好神奇,一个属性就完美解决了整个问题。那到底是为什么呢?(注意,Elevation
只能用在 API19 以上。)
仅仅是添加了 elevation
属性就 OK 了,要整明白为什么,就得先去看看 API 里这个 elevation
到底是什么意思。
大致就是说
elevation
是 view 在 Z 轴上的位置,可以用一个浮点数加长度的单位来表示,一般情况下应该是 dp(这里的 sp 个人觉着应该是不对的)。
在处理这个之前,首先我们需要了解一个概念,组件在 Z 轴上的高度等于 translationZ + elevation
。
首先,我们看这个问题,TextView 被 FloatingActionButton
覆盖了。这只说明一个问题:FloatingActionButton 一定是在 Z 轴上有默认的高度的,因为是同是 Z 轴的值,只有当 FloatingActionButton 在 Z 轴的高度大于 TextView 在 Z 轴的高度时,TextView 才会出现 TextView 被覆盖的情况。而在帧布局里后添加的组件会覆盖在先添加的组件上,如果 TextView 和 FloatingActionButton 在 Z 轴上的位置一样的话,TextView 就会显示在 FloatingActionButton 上了。这样我们就可以先打印出 translationZ
和 elevation
的默认值。
1 | float elevation = fab.getElevation(); |
我用的测试机是小米2sc,得到的 elevation
值是 12.0 ,fabTranslationZ
的值是 0.0 。因为手机分辨率是 720P,所以这个 elevation
默认值就是 6dp ,fabTranslationZ
默认值是 0dp 。
那样,这样是不是就彻底解决我们的问题了呢?答案是:否!以内即便设置了 android:elevation="6dp"
,正常显示 TextView
不会被覆盖,但是当我们点击按压 FloatingActionButton
的时候,ripple 散开,这个 TextView
还是会覆盖掉。所以说这样处理并不完美。因为是点击按压的时候出现了问题,那我们就再看 FloatingActionButton
是否有相关的属性,刚好就有一个 app:pressedTranslationZ
属性,而它也是有默认值的,当我们把它的值设置为 0dp 时,就完美解决了按压时被覆盖的问题。
既然明确了上面的结论,那接下来处理就非常简单了。终极的解决方案就是:设置 FloatingActionButton
的默认阴影为 0dp ,app:elevation="0dp"
;因为 fabTranslationZ
默认值是 0dp ,所以不用管;然后设置 app:pressedTranslationZ
的值为 0dp ,app:pressedTranslationZ="0dp"
,来保证按压时 TextView 不被覆盖。(这样做牺牲了好多其他的效果,还是不完美…)
最后我们来看一看关于 FloatingActionButton
的默认值 dimens.xml
,验证一下我们的设置。当然还要感谢Mr_Wrong丶同学帮我一起来验证解决问题。