利用 StateListAnimator 为你的点击加个动画吧!

利用 StateListAnimator 为你的点击加个动画吧!

正文共: 2894字 9图

预计阅读时间: 8分钟

一、前言

对于 App 而言,可点击的 Button 或者 TextView ,都是非常常见的元素。而通常,为了优化交互,让用户在点击这些控件的时候,有一个视觉上的效果,通常我们会使用 <selector> 或者 StateListDrawable 制造一个点击按下的背景切换,来达到视觉上的差异,让用户明显的感觉到自己按下了按钮。

StateListDrawable 本质上是多个 Drawable 的集合,然后在 View 不同的状态下,去切换展示对应状态应该显示的 Drawable,这种切换的过程是迅速而生硬的。

而从 Api 21 开始,引入了新的管理 View 状态显示的机制,那就是 StateListAnimator。它遵循 Material Design 的原则 "Motion provides meaning",也就是当用户和你的 App 交互的时候,提供合理的视觉反馈。StateListAnimator 和 StateListDrawable 比起来,可以使用一种过度的效果来达到响应 View 状态的变化,视觉上会比较柔和。其实说到过度的效果,我想大家应该清楚,实际上就是做了一个动画效果。

那么接下来让我们看看实际效果。

二、常规的状态控制

在 Api Level 21 之前,我们如果想对 View 的不同状态,显示不同的 Drawable 效果的话,可以使用 StateListDrawable ,它可以在 drawable-xml 里通过 <selector/> 来进行定义,使用起来非常的方便。

这个相信大家都比较熟悉了,这里直接上例子了。

首先我们在 ./res/drawable 目录下,定义一个 btn_press_bg.xml 文件。

利用 StateListAnimator 为你的点击加个动画吧!

这里只定义了普通状态和 android:state_pressed 的状态,就是在按下的时候的状态。

之后我们再定义一个 TextView ,通过 android:background 属性,将我们前面定义好的 btn_press_bg 设置上去。来看看运行的效果。

利用 StateListAnimator 为你的点击加个动画吧!

<selector/> 本质上是定义了多个与 View 状态对应的 Drawable,然后在 View 状态切换的时候,迅速的切换显示的 Drawable。它的切换是没有任何过度的,算是比较生硬吧。

三、状态过度效果

而在 Api Level 21 之后,我们可以通过 StateListAnimator 来实现 Material Design 的按下效果。

StateListAnimtor 使用起来非常的简单:

  1. 在 res 中创建一个 animator 目录。

  2. 在其中创建一个 xml 资源文件,就是一个 <selector/>

  3. 在 xml 资源中使用 <selector/> 中,定义我们 View 切换状态时候的动画,其实就是一个个 <objectAnimator/>

  4. 最终将定义好的 animtor 通过 View 的 setStateListAnimator() 方法或者 android:stateListAnimator 属性,设置到 View 上。

到此就算是完成了所有的关键步骤。

下面来举个例子看看。

首先在 /res/animtor 目录下,创建一个 btn_press_animator.xml 文件。

利用 StateListAnimator 为你的点击加个动画吧!

可以看到,和 StateListDrawable 一样,它也是通过 android:state_xxx 属性来定义不同的 Animator 的,如果存在多个 Animator ,可以使用 <set/> 标签将其包裹起来。 这里只是简单的在 state_pressed 的时候,做了一个缩小的动画。

然后,定义一个 View,为其设置属性 android:stateListAnimator="@animator/btn_press_animator"

利用 StateListAnimator 为你的点击加个动画吧!

最终,来看看执行后的效果。

利用 StateListAnimator 为你的点击加个动画吧!

四、StateListAnimator的原理

这里可以看到,实际上 StateListAnimator 操作的就是 ObjectAnimator 。所以 ObjectAnimator 能定义的效果,它都可以进行设置。

4.1 如何动态加载 StateListAnimator 资源

前面我们知道如何在 xml 里,通过属性设置一个 StateListAniamtor,而如果我们需要动态的设置它,可以使用 setStateListAnimator() 方法,那么我们面临的问题就是如何在 Java 代码中,动态的生成一个 StateListAnimator 呢?

通常,我们依然会通过 xml 来定义一个 StateListAniamtor,那么我们如何来加载它呢?看看 View 的源码就清楚了。

利用 StateListAnimator 为你的点击加个动画吧!

这里,是依赖 AnimatorInflater.loadStateListAnimator() 方法来加载 StateListAnimator 的,当然,它接收的是一个 xml 中定义好的 StateListAnimator。

如果想要完全依赖代码创建一个 StateListAnimator 的话,可以直接 new 一个它,然后使用 addState() 方法,添加不同状态的 Drawable。

利用 StateListAnimator 为你的点击加个动画吧!

这几个类和方法,都是 Api Level 21 之后才支持的。

4.2 View 如何通知 StateListAniamtor

那么,StateListAnimator 又是如何响应 View 状态的变化的呢?

首先,StateListAniamtor 有一个 setState() 的方法,在 View 状态改变的时候,它会去调用这个方法。

利用 StateListAnimator 为你的点击加个动画吧!

View 会在 jumpDrawablesToCurrentState()drawableStateChanged() 的时候,调用 setState() 方法,并将当前 View 的状态传递进来,StateListAniamtor 就通过这个状态,进行不同的动画执行。

4.3 避免 Material 默认的按下效果

如果当前主题继承自 Material Design 的主题,会导致所有的 Button 按下的操作,有一个 Z 轴的变换效果,类似于一个按下的效果,你碰到你就知道了。

如果想要去除这个效果,可以将 android:stateListAnimator 属性,设置为 @null,就可以去除它了。

五、小结

StateListAnimator 和比较常用的 StateListDrawable 作用其实很类似,所以很多场景都是可以相通的。类似本文举例的按钮按下效果,还有如果做 TV App 的话,也有一些焦点放大效果,都是可以使用 StateListAniamtor 来完成的,当然前提是放弃低版本。

对于低于 Api Level 21 之下的版本,可以尝试对 View 进行重写,来实现类似的效果,也可以直接使用 Github 上的第三方库,具体情况还是具体分析吧。

今天在承香墨影公众号的后台,回复『成长』。我会送你一些我整理的学习资料,包含:Android反编译、算法、设计模式、虚拟机、Linux、Web项目源码。

利用 StateListAnimator 为你的点击加个动画吧!

推荐阅读:

利用 StateListAnimator 为你的点击加个动画吧!

目前5000+人已关注加入我们

利用 StateListAnimator 为你的点击加个动画吧!利用 StateListAnimator 为你的点击加个动画吧!利用 StateListAnimator 为你的点击加个动画吧!利用 StateListAnimator 为你的点击加个动画吧!利用 StateListAnimator 为你的点击加个动画吧!利用 StateListAnimator 为你的点击加个动画吧!利用 StateListAnimator 为你的点击加个动画吧!利用 StateListAnimator 为你的点击加个动画吧!

利用 StateListAnimator 为你的点击加个动画吧!利用 StateListAnimator 为你的点击加个动画吧!利用 StateListAnimator 为你的点击加个动画吧!利用 StateListAnimator 为你的点击加个动画吧!利用 StateListAnimator 为你的点击加个动画吧!利用 StateListAnimator 为你的点击加个动画吧!利用 StateListAnimator 为你的点击加个动画吧!利用 StateListAnimator 为你的点击加个动画吧!


听说喜欢留言的人,运气都不会太差

点击『阅读原文』查看更多精彩内容