实现的效果
看完本文,如下效果的实现可以完全拿捏住了,并且还非常简单噢~:
a. 按下时透明度的变化
b. 按下时塞入蒙层
可以完美覆盖大部分的点击场景了,如果没有,那就快去说服设计师更换方案![狗头保命]
按下时透明度的变化(GIF 中左边 Icon 的点击效果)
一般的思路是 xml 配置 selector,放两张图片,完美解决。但这样通用性也太差了点吧,每张图片都要配置一个 selector,有没有更好点的办法呢?这里我采用的方式是 重写 onTouch() :
/**
* 对当前 View 实现按下透明度变化的效果
*/
@SuppressLint("ClickableViewAccessibility")
fun View.fadeWhenTouch(pressedAlpha: Float = 0.5F) {
this.setOnTouchListener { v, event ->
when (event?.action) {
MotionEvent.ACTION_DOWN -> v?.alpha = pressedAlpha
MotionEvent.ACTION_UP -> v?.alpha = 1F
MotionEvent.ACTION_CANCEL -> v?.alpha = 1F
}
false
}
}
// 实际使用时, 进行如下调用:
binding.ivLoveYou.fadeWhenTouch()
- 使用拓展函数,在
MotionEvent.ACTION_DOWN时设置 View 的透明度,在松手时取消透明度的设置 - 调用时直接使用
view.fadeWhenTouch()即可,非常方便,如果存在多个 View 需要设置的情况,可以使用 ContraintLayout 的 Group 遍历之后一并设置一下~
按下时塞入蒙层
这里当然也可以用 selector 来解决问题。但有没有办法直接用一个色值就可以搞定呢?实在无法忍受多余的资源文件!答案是有的,用 Tint !
-
配置 selector_pressed_overlay.xml 放在 res/color/ 目录下:
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true" android:color="#33000000"/> <item android:color="#00000000" /> </selector>a. 按下时,我们展示 20% 透明度的黑色
b. 其他状态则显示透明色
-
对于普通 View 的 Background 按下时需要塞入蒙层的情况 (GIF 中间 Icon 的点击效果)
<ImageView ... android:background="@drawable/jiaran_angry_drawable" android:backgroundTintMode="src_atop" android:backgroundTint="@color/selector_pressed_overlay" android:clickable="true" />a. background:View 所展示的 Background
b. backgroundTintMode:tint 叠加的模式,使用 src_atop 可以完美符合需求
c. backgroundTint:1 中的 color 配置文件,在其中配置按下态的逻辑
d. clickable:在没有实现 onClick() 的情况下,可以响应按下态
-
对于 ImageView 的 Drawable 按下需要塞入蒙层的情况 (GIF 中右边 Icon 的点击效果)
<ImageView ... android:clickable="true" android:src="@drawable/jiaran_remove_bg" android:tintMode="src_atop" app:tint="@color/selector_pressed_overlay" />可以参考 Background 的实现进行理解,逻辑是一样的
Tips
-
对于 RecyclerView 中的 item ,按下时塞入蒙层的实现有一点点区别:
<!-- tintMode 需要更换为 src_over --> android:backgroundTintMode="src_over" -
如果 View 没有背景,但需要实现按下塞入蒙层的效果。那么,可以将其 background 设置成透明的,再按照如上进行配置即可
-
如果需要自己手动裁切圆角,除了使用 CardView,还可以使用
ViewOutlineProvider实现,减少 View 的嵌套,具体可参考 这篇Blog -
本文源码可以参考该 仓库