In this tutorial, we’ll learn how to apply a reveal with bounce animation to any view in Android. I used this particular reveal animation to show bonus points in a previous application. For the purposes of this tutorial, we’ll be using it on a simple custom view. This final result can be seen at the end of the article.
在本教程中,我们将学习如何将带有反弹动画的显示应用于Android中的任何视图。 我使用此特定的揭示动画在以前的应用程序中显示奖励积分。 就本教程而言,我们将在简单的自定义视图上使用它。 最终结果可以在文章末尾看到。
First, let’s lay down the foundation on which we’ll add the animation. That includes:
首先,让我们为添加动画奠定基础。 包括:
The view we want to reveal. 我们想要揭示的观点。 The activity in which it’ll reside. 它将驻留的活动。 The animator resource directory. 动画师资源目录。It’s worth noting here that you don’t have to use an activity. This is just what I’ll be using for this tutorial.
值得一提的这里,你不必使用活动。 这就是本教程将使用的内容。
The custom view we’ll be using is a simple ConstraintLayout with a TextView in the center. It’ll look like this:
我们将使用的自定义视图是一个简单的ConstraintLayout中间是一个TextView 。 它看起来像这样:
Here’s the XML for this view. We’ll name it view_bonus:
这是该视图的XML。 我们将其命名为view_bonus :
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@android:color/white" android:elevation="8dp"> <TextView android:id="@+id/textView3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="32dp" android:layout_marginBottom="32dp" android:text="BONUS POINTS" android:textSize="32sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>The activity in which we’ll put this view is the main activity (the launch activity). We’ll position and constraint it in its fully shown state, and we’ll give it an ID of vBonus. We’ll also add a button at the bottom that we’ll use to demonstrate the reveal animation. We’ll give that an ID of bRevealBounce. This is how it’ll look:
我们将其放在该视图中的活动是主要活动(启动活动)。 我们将其定位和约束为其完全显示的状态,并为其指定ID vBonus 。 我们还将在底部添加一个按钮,用于演示显示动画。 我们给它一个ID为bRevealBounce 。 外观如下:
Here’s the XML for the activity. Notice that we’ll be setting the visibility of vBonus to gone since we’ll be revealing it later.
这是活动的XML。 注意,我们将设置vBonus的可见性gone因为我们稍后将对其进行揭示。
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <include android:id="@+id/vBonus" layout="@layout/view_bonus" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginEnd="16dp" android:visibility="gone" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <Button android:id="@+id/bRevealBounce" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginEnd="16dp" android:layout_marginBottom="16dp" android:text="Reveal Bounce" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>If you don’t have the animator resource directory under “res,” then you’ll have to add it. To do that, right-click on “res” -> “New” -> “Android Resource Directory.”
如果在“ res”下没有动画师资源目录,则必须添加它。 为此,请右键单击“ res”->“ New”->“ Android Resource Directory”。
Under “Resource type,” choose “animator,” then click OK.
在“资源类型”下,选择“动画师”,然后单击“确定”。
Now that you have an animator resource directory, let’s go ahead and add the Animator Resource File in which we’ll implement the animation. To do that, right-click on “animator” -> “New” -> “Animator Resource File.”
现在您已经有了一个动画师资源目录,让我们继续添加动画师资源文件,在其中我们将实现动画。 为此,请右键单击“动画”->“新建”->“动画资源文件”。
The animator resource file will consist of a set of animations, so make sure the “Root element” is “set.” Name the file reveal_bounce.
动画师资源文件将包含一组动画,因此请确保“根元素”已设置。 将文件命名为reveal_bounce 。
Now that we’re ready to implement the actual animation, let me briefly explain what we’re setting out to do. We want the following things to happen sequentially:
现在我们已经准备好实现实际的动画了,让我简要地解释一下我们打算要做的事情。 我们希望以下事情依次发生:
Completely expand vBonus horizontally and at the same time expand it just a little bit vertically so that it’s not completely hidden.
完全水平扩展vBonus ,同时垂直扩展一点,这样就不会完全隐藏。
Completely expand vBonus vertically with bounce.
垂直完全bounce vBonus 。
Wait a little bit, then completely shrink vBonus vertically and animate its alpha to 0 at the same time so that it disappears by the end of it.
稍等片刻,然后垂直完全缩小vBonus并同时将其alpha动画为0,以便在其结束时消失。
The default ordering of a set is together — not sequentially — so the first thing we need to do is explicitly set the ordering of the parent set in reveal_bounce to sequentially.
集合的默认排序是together -而不是sequentially -因此,我们需要做的第一件事是将reveal_bounce中的父集合的排序显式设置为sequentially 。
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="sequentially"> </set>In this parent set, we’ll add three more sets implementing the three steps we explained earlier.
在此父集中,我们将添加三个以上的集,以实现我们前面解释的三个步骤。
The first set will have two objectAnimators. One will animate the property scaleX from 0f to 1f, which means it’ll completely expand the view horizontally. The second one will animate the property scaleY from 0f to 0.1f, which means it’ll expand the view vertically just a little bit. We’ll set the duration to 100 milliseconds for this example.
第一组将具有两个objectAnimators 。 可以将scaleX属性从0f设置为1f,这意味着它将完全水平扩展视图。 第二个将使scaleY属性从0f到0.1f进行动画处理,这意味着它将垂直扩展视图一点。 在此示例中,我们将持续时间设置为100毫秒。
The f after each number indicates it’s a float value and not an integer.
每个数字后面的f表示它是浮点值,而不是整数。
<set> <objectAnimator android:duration="100" android:propertyName="scaleX" android:valueFrom="0f" android:valueTo="1f" /> <objectAnimator android:duration="100" android:propertyName="scaleY" android:valueFrom="0f" android:valueTo="0.1f" /> </set>The second set will have one objectAnimator that will animate the property scaleY from 0.1f to 1f, which means it’ll completely expand the view vertically. We’ll set the duration to 300 milliseconds for this example.
第二组将具有一个objectAnimator ,它将使scaleY属性从0.1f变为1f,这意味着它将完全垂直扩展视图。 在此示例中,我们将持续时间设置为300毫秒。
To add a bounce, we’ll have to set the interpolator property to bounce_interpolator. This interpolator already exists and you can just use it.
要添加bounce ,我们必须将interpolator属性设置为bounce_interpolator 。 该插值器已经存在,您可以使用它。
<set> <objectAnimator android:interpolator="@android:anim/bounce_interpolator" android:duration="300" android:propertyName="scaleY" android:valueFrom="0.1f" android:valueTo="1f" /> </set>The third and last set will have two objectAnimators. One will animate the property scaleY from 1f to 0f, which means it’ll completely shrink the view vertically. The second one will animate the property alpha from 1f to 0f, which means it’ll completely fade out the view.
第三组和最后一组将具有两个objectAnimators 。 一个可以将属性scaleY从1f设置为0f的动画,这意味着它将完全垂直缩小视图。 第二个将使属性alpha从1f变为0f,这意味着它将完全淡化视图。
We’ll set the duration to 250 milliseconds for this example and have it wait 350 milliseconds before it starts just so that the view is visible for a little bit before it goes away.
在本示例中,我们将持续时间设置为250毫秒,并让其等待350毫秒才开始播放,以使视图在消失之前可以看到一点点。
<set> <objectAnimator android:duration="250" android:startOffset="350" android:propertyName="scaleY" android:valueFrom="1f" android:valueTo="0f" /> <objectAnimator android:duration="250" android:startOffset="350" android:propertyName="alpha" android:valueFrom="1f" android:valueTo="0f" /> </set>The three sets together in reveal_bounce will look like this:
reveal_bounce的三个集合将如下所示:
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="sequentially"> <set> <objectAnimator android:duration="100" android:propertyName="scaleX" android:valueFrom="0f" android:valueTo="1f" /> <objectAnimator android:duration="100" android:propertyName="scaleY" android:valueFrom="0f" android:valueTo="0.1f" /> </set> <set> <objectAnimator android:interpolator="@android:anim/bounce_interpolator" android:duration="300" android:propertyName="scaleY" android:valueFrom="0.1f" android:valueTo="1f" /> </set> <set> <objectAnimator android:duration="250" android:startOffset="350" android:propertyName="scaleY" android:valueFrom="1f" android:valueTo="0f" /> <objectAnimator android:duration="250" android:startOffset="350" android:propertyName="alpha" android:valueFrom="1f" android:valueTo="0f" /> </set> </set>Let’s apply the animation! In our MainActivity, we’ll be doing a few things:
让我们应用动画! 在MainActivity ,我们将做一些事情:
Add a property of type Animator. This will hold the animation itself, the view on which the animation will happen, and a listener for when the animation starts and when the animation ends.
添加类型为Animator的属性。 这将保存动画本身,将在其上发生动画的视图以及一个动画开始时间和动画结束时间的侦听器。
Add a setup function that will set up our Animator with all of the above, which will be invoked in the onCreate function.
添加一个setup函数,将使用以上所有内容来设置我们的Animator ,并将在onCreate函数中调用它。
Add a function to start the animation. Although starting the animation is already a one-liner, we do want to check if the animation has started already so that we can prevent starting the animation again while it’s already started. 添加一个函数以开始动画。 尽管开始播放动画已经是一种趋势,但我们还是要检查动画是否已经开始播放,以便我们可以防止在动画开始播放后再次开始播放动画。Add an OnClickListener to bRevealBounce that will invoke the start animation function.
向bRevealBounce添加一个OnClickListener ,它将调用start animation功能。
Since we’ll be setting up the Animator in onCreate, instead of using an optional in Kotlin, we’ll be using lateinit, which is basically a non-optional with a promise to initiate before use. We’ll name it revealBounceAnim.
由于我们将在onCreate设置Animator ,而不是在Kotlin中使用可选项,因此我们将使用lateinit ,这基本上是一个非可选项,并承诺在使用前会初始化。 我们将其命名为revealBounceAnim 。
class MainActivity : AppCompatActivity() { private lateinit var revealBounceAnim: Animator // Hidden code... }The setup function will load the animation, set the target view to vBonus, add a listener that will make vBonus visible before animation, and hide the view when the animation ends. We’ll name that function setupRevealBounceAnimation.
setup功能将加载动画,将目标视图设置为vBonus ,添加一个侦听器以使vBonus在动画之前可见,并在动画结束时隐藏视图。 我们将其命名为setupRevealBounceAnimation 。
To load the animation, we’ll use AnimatorInflator.loadAnimator, which takes a context and the animation file we created earlier. This will return an Animator that we’ll set revealBounceAnim to.
要加载动画,我们将使用AnimatorInflator.loadAnimator ,它需要一个上下文和我们之前创建的动画文件。 这将返回一个Animator ,我们将其设置为revealBounceAnim 。
To set the target view of the animation, we’ll use the setTarget function on revealBounceAnim.
要设置动画的目标视图,我们将在revealBounceAnim上使用setTarget函数。
To add a listener, we’ll use the addListener function on revealBounceAnim. It takes an AnimatorListener. We particularly care about two callbacks here:
要添加侦听器,我们将在revealBounceAnim上使用addListener函数。 它需要一个AnimatorListener 。 我们在这里特别关心两个回调:
The onAnimationStart callback in which we’ll make vBonus visible and not transparent.
我们将使vBonus可见且不透明的onAnimationStart回调。
The onAnimationEnd callback in which we’ll hide vBonus.
我们将隐藏vBonus的onAnimationEnd回调。
class MainActivity : AppCompatActivity() { // Hidden code... private fun setupRevealBounceAnimation() { revealBounceAnim = AnimatorInflater.loadAnimator( this, R.animator.reveal_bounce ) revealBounceAnim.setTarget(vBonus) revealBounceAnim.addListener(object : Animator.AnimatorListener { override fun onAnimationRepeat(animation: Animator?) { } override fun onAnimationCancel(animation: Animator?) { } override fun onAnimationEnd(animation: Animator?) { vBonus?.visibility = View.GONE } override fun onAnimationStart(animation: Animator?) { vBonus.visibility = View.VISIBLE vBonus.alpha = 1f } }) } // Hidden code... }The reason why vBonus is treated like an optional in onAnimationEnd is just in case the application is dismissed before the animation ends, in which case the view will be gone and might cause the application to crash.
之所以将vBonus视为vBonus中的可选onAnimationEnd是为了防止在动画结束之前关闭应用程序,在这种情况下视图将消失并可能导致应用程序崩溃。
It’s worth mentioning here that this is a quick and dirty implementation. Ideally, we’d want to use reactive patterns so that we wouldn’t care if the application is dismissed or not. I’ll leave that topic for a different day, though.
在这里值得一提的是,这是一个快速而肮脏的实现。 理想情况下,我们希望使用React模式,这样我们就不会在乎是否关闭应用程序。 不过,我将把这个话题留在另一天。
To start the animation, we’ll add a function that will make sure the animation isn’t started already before starting the animation. We’ll name it startRevealBounceAnimation.
要开始动画,我们将添加一个函数,以确保在开始动画之前尚未开始动画。 我们将其命名为startRevealBounceAnimation 。
class MainActivity : AppCompatActivity() { // Hidden code... private fun startRevealBounceAnimation() { if (!revealBounceAnim.isStarted) { revealBounceAnim.start() } } }Last but not least, in onCreate, we’ll invoke setupRevealBounceAnimation and then we’ll add an OnClickListener to bRevealBounce that will simply invoke startRevealBounceAnimation.
最后但并非最不重要的一点,在onCreate ,我们将调用setupRevealBounceAnimation ,然后将一个OnClickListener添加到bRevealBounce ,该OnClickListener将仅调用startRevealBounceAnimation 。
class MainActivity : AppCompatActivity() { // Hidden code... override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) setupRevealBounceAnimation() bRevealBounce.setOnClickListener { startRevealBounceAnimation() } } // Hidden code... }The whole MainActivity file will look like this:
整个MainActivity文件如下所示:
package com.example.myapplication import android.animation.Animator import android.animation.AnimatorInflater import android.os.Bundle import android.view.View import androidx.appcompat.app.AppCompatActivity import kotlinx.android.synthetic.main.activity_main.* class MainActivity : AppCompatActivity() { private lateinit var revealBounceAnim: Animator override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) setupRevealBounceAnimation() bRevealBounce.setOnClickListener { startRevealBounceAnimation() } } private fun setupRevealBounceAnimation() { revealBounceAnim = AnimatorInflater.loadAnimator( this, R.animator.reveal_bounce ) revealBounceAnim.setTarget(vBonus) revealBounceAnim.addListener(object : Animator.AnimatorListener { override fun onAnimationRepeat(animation: Animator?) { } override fun onAnimationCancel(animation: Animator?) { } override fun onAnimationEnd(animation: Animator?) { vBonus?.visibility = View.GONE } override fun onAnimationStart(animation: Animator?) { vBonus.visibility = View.VISIBLE vBonus.alpha = 1f } }) } private fun startRevealBounceAnimation() { if (!revealBounceAnim.isStarted) { revealBounceAnim.start() } } } Final result. 最后结果。That’s it! When you click the button, the bonus view will reveal itself with a bounce before it disappears again. I hope this was useful to you. Until next time, this is Dev Bites signing out!
而已! 当您单击按钮时,红利视图将在再次消失之前以弹跳的形式显示出来。 我希望这对您有用。 直到下次,这是Dev Bites退出!
翻译自: https://medium.com/better-programming/reveal-animation-with-bounce-in-android-578454f20d0b
相关资源:android控件的抖动效果, 可以实现上下,左右抖动效果