很多人都知道 Android 的卡片式点击效果,这个 selector 是画在前景上的而不是背景上的,虽然我们一般都是用背景色。这个点击效果实现方式也并不难,下面就给出几种情况下的方法。
下图是 Google Play 应用中按压效果的一个截图:
若为 FrameLayout
添加前景色会非常简单,因为 FrameLayout 本身就有这样一个方法叫 setForeground。实际上,只需要通过在 XML 中android:foreground
或代码中动态传一个 selector 作为参数,然后调用 setForeground 就可以了。
若不为 FrameLayout
别担心,这也不会很难。我们只要设置给 selector 设置合适的状态(pressed, focused …),然后设置边界并且在视图画好自己后再画它。这样,selector 就会覆盖在视图之上。
- Changing the State
在 View 这个类,每次视图改变自己的 drawable state 时都会调用的方法:drawableStateChanged
|
|
- Updating the Drawable Bounds
每次视图改变大小时都会调用的方法:onSizeChanged
|
|
- Drawing the Selector
分为两种情况:
(1) 视图不是 ViewGroup
必须在调用父类的 onDraw(Canvas canvas) 之后再画 selector。
|
|
(2) 视图是 ViewGroup
必须在画好所有的子视图之后在画,也就是说在调用 dispatchDraw(Canvas canvas) 之后。
|
|
- Drawing an Animated Drawable
如果你的 drawable 是动画类型的,那就还有些事情需要做。假设我们有一个有android:exitFadeDuration
属性的 selector,也就是说当 selector 改变它的状态的时候,旧的状态会慢慢淡出。
首先,我们需要在 onDraw() 或者 dispatchDraw() 方法中添加 selector 的 draw(Canvas) 方法,如下:
|
|
然后,我们要重写 jumpDrawablesToCurrentState 方法来通知 selector 去做状态之间的转换动画,重写 verifyDrawable 方法来告诉视图我们在显示自己的 drawable。
|
|
但是,jumpToCurrentState 方法里面做了什么呢?我们来 DrawableContainer 类中的一点源码。
|
|
我们看到 jumpToCurrentState 中会调用 invalidateSelf,下面再看下 invalidateSelf 方法的源码。
|
|
可以看到如果 callback 为空,就不会重绘 drawable。所以我们在初始化 selector 时要设置 callback。
|
|
现在你的 selector 就有淡出动画效果了!
EXTRA
- 把默认的背景设为前景
你可以获得你主题中的默认背景的 selector,然后把它设为前景的 selector。
|
|
原文链接:DZone 作者:Antoine Merle