View animation and frame animation of Android animation

Android animation can be divided into three categories:

1> View animation is also known as: tweening 

2> Frame animation

3> Property animation

 

==================[ View Animation ]=========================

There are 5 types:

Alpha                             gradient transparency animation effect
scale                             gradient size scaling animation effect
translate                        screen transition position move animation effect
rotate                            screen transfer rotation animation effect
layoutAnimation            container control application unified animation

 

 

First, the specific steps for creating a directory are as follows:

 

Choose: anim directory

 

OK, look at the directory, create an animation file: set

 

Named: my_animat

 

Okay, let's add the animation we need to this set.

It can be an animation or a combination of multiple animations    

Now let’s take one by one to demonstrate the horizontal motion painting:

【translate】

Look at the setting of the animation target View, a TextView is used.  Note: The width and height used are 300px pixels,,, pixels,,, pixels

Why use px, I will talk about it  

<TextView
            android:id="@+id/tv_animator"
            android:layout_width="300px"
            android:layout_height="300px"
            android:background="@color/color_00a3f3"
            android:text="animator"
            android:textColor="@color/color_7e4513"
            android:gravity="center"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
    />

 

Then the animation translate_ani.xml       note: fillAfter="true"  View will stay at the end of the animation at the end

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:fillAfter="true">

    <!-- 平移  对应 TranslateAnimation
    fromXDelta,fromYDelta   起始时X,Y座标,如果是0,0,就从远处开启
    toXDelta, toYDelta     动画结束时X,Y的座标 这个坐标是相对于 原始位置(0,0)的
    看下 toXDelta  toYDelta  和TextView 宽高同是 300
    -->
    <translate
            android:fromXDelta="0"
            android:fromYDelta="0"
            android:toXDelta="300"
            android:toYDelta="300"
            android:duration="500">
    </translate>

</set>

 

Take a look at the original screenshot

 

Look at the layout in Activity: activity_animator.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".animator.AnimatorActivity">


    <TextView
            android:id="@+id/tv_animator"
            android:layout_width="300px"
            android:layout_height="300px"
            android:background="@color/color_00a3f3"
            android:text="目标动画"
            android:textColor="@color/color_7e4513"
            android:gravity="center"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
    />


    <TextView
            android:id="@+id/tv_animator1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="@dimen/dp10"
            android:layout_marginTop="@dimen/dp100"
            android:text="平移动画"
            android:background="@color/color_999999"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintTop_toBottomOf="@id/tv_animator"/>

    <TextView
            android:id="@+id/tv_animator2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="@dimen/dp10"
            android:layout_marginTop="@dimen/dp10"
            android:text="透明动画"
            android:background="@color/color_999999"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintTop_toBottomOf="@id/tv_animator1"/>

    <TextView
            android:id="@+id/tv_animator3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="@dimen/dp10"
            android:layout_marginTop="@dimen/dp10"
            android:text="旋转动画"
            android:background="@color/color_999999"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintTop_toBottomOf="@id/tv_animator2"/>

    <TextView
            android:id="@+id/tv_animator4"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="@dimen/dp10"
            android:layout_marginTop="@dimen/dp10"
            android:text="缩放动画"
            android:background="@color/color_999999"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintTop_toBottomOf="@id/tv_animator3"/>
</android.support.constraint.ConstraintLayout>

 

 

 

Activity code:

package com.leo.dicaprio.myutilapp.animator

import android.content.Context
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.view.animation.AnimationUtils
import android.widget.Toast
import com.leo.dicaprio.myutilapp.R
import kotlinx.android.synthetic.main.activity_animator.*
import org.jetbrains.anko.startActivity

class AnimatorActivity : AppCompatActivity() {

    companion object {
        fun launch(context: Context) {
            context.startActivity<AnimatorActivity>()
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_animator)
        tv_animator.setOnClickListener { Toast.makeText(this, "被单击了", Toast.LENGTH_LONG).show() }
        tv_animator1.setOnClickListener { startAni1() }
        tv_animator2.setOnClickListener { startAni2() }
        tv_animator3.setOnClickListener { startAni3() }
        tv_animator4.setOnClickListener { startAni4() }
    }


    /**
     *      平移动画
     * */
    private fun startAni1() {
        //先加载 平移动画
        val animation = AnimationUtils.loadAnimation(this, R.anim.translate_ani)
        tv_animator.startAnimation(animation)
    }

    

}

 

Click once, the animation effect will not produce gif, directly upload the final result

 

You can see the final result. At this time, the mobile phone opened the border layout of the developer mode.

Analysis:

The target's View width and height are 300*300 pixels, and now the toXDelta and toYDelta of the animation are both 300, which means moving 300 pixels in the positive direction of the XY axis.

Why is it so sure that the unit of toXDelta is pixel? From the screenshot, it can be understood that the target View is based on the distance moved by the source point (upper left corner coordinates) in the XY direction, which is exactly the width and height of the target. . .

by the way! At this time, if you click on the blue area, Taost will not be played. Toast will only be played when you click on the original position. So the View animation has not changed

View properties. Therefore, if the target animation View has a click event, the function cannot be achieved with View animation. . . Pay attention to this.

 

Alright, basically understandable. In fact, the translate tag corresponds to TranslateAnimation() 

You can use it, the code is changed to:

    /**
     *      平移动画
     * */
    private fun startAni1() {
        //先加载 平移动画
//        val animation = AnimationUtils.loadAnimation(this, R.anim.translate_ani)
//        tv_animator.startAnimation(animation)

        //单位是像素
        val translateAnimation = TranslateAnimation(0F, 300F,0F , 300F)
        translateAnimation.fillAfter = true//停留在结束地方
        translateAnimation.duration = 500//时间
        tv_animator.startAnimation(translateAnimation)
    }

The same effect! ! !

In addition, through this TranslateAnimation, you can also monitor the execution status of the animation, such as: start, end, repeat...

such as:

    /**
     *      平移动画
     * */
    private fun startAni1() {
        //先加载 平移动画
//        val animation = AnimationUtils.loadAnimation(this, R.anim.translate_ani)
//        tv_animator.startAnimation(animation)

        val translateAnimation = TranslateAnimation(0F, 300F, 0F, 300F)
        translateAnimation.setAnimationListener(object : Animation.AnimationListener {
            override fun onAnimationRepeat(animation: Animation?) {
                //动画重复
            }

            override fun onAnimationEnd(animation: Animation?) {
                //动画结束
            }

            override fun onAnimationStart(animation: Animation?) {
                //动画开始
            }

        })
        translateAnimation.fillAfter = false//停留在结束地方
        translateAnimation.duration = 500//时间
        tv_animator.startAnimation(translateAnimation)
    }

 

【alpha】

Transparency is relatively simple. . . . On the alpha_ani.xml code:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:fillAfter="true">

    <!--透明
        fromAlpha:开始时透明度 0.0- 1.0   0.0全透明  1.0不透明
        toAlpha: 结束时透明度 0.0- 1.0
        duration:动画持续时间 单位 毫秒
        fillAfter:动画结束后是否停留在结束位置,true停留
        -->
    <alpha android:fromAlpha="1"
           android:toAlpha="0"
           android:duration="10000"
    >
    </alpha>

</set>

 

Activity reference

    /**
     *      透明动画
     * */
    private fun startAni2() {
        //先加载 透明动画
        val animation = AnimationUtils.loadAnimation(this, R.anim.alpha_ani)
        tv_animator.startAnimation(animation)

        /*
        *       或者
        * */
        val alphaAnimation = AlphaAnimation(1.0F, 0F)
        alphaAnimation.fillAfter = true
        alphaAnimation.duration = 5000
        tv_animator.startAnimation(alphaAnimation)
    }

 

【Rotate】

Rotation, generally four parameters

fromDegrees    开始时的角度
toDegrees      结束时角度 ,正代表顺时针
pivotX         旋转中心轴点 X坐标 不指定 默认是View 左上角 X坐标   单位像素
pivotY         旋转中心轴点 Y坐标 不指定 默认是View 左上角 Y坐标   单位像素

 

Don’t talk nonsense, go to the target View, haha, it’s also a TextView, which is also 300*300 px

    <TextView
            android:id="@+id/tv_animator"
            android:layout_width="300px"
            android:layout_height="300px"
            android:background="@color/color_00a3f3"
            android:text="目标动画"
            android:textColor="@color/color_7e4513"
            android:gravity="center"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
    />

 

 

Upload animation file: anim /rotate_ani.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:fillAfter="true">

    <!--
        fromDegrees  	开始时的角度
        toDegrees    	结束时角度 ,正代表顺时针
        pivotX  	    旋转中心轴点 X坐标 不指定 默认是View 左上角 X坐标
        pivotY 	        旋转中心轴点 Y坐标 不指定 默认是View 左上角 Y坐标
        -->
    <rotate android:fromDegrees="0"
            android:toDegrees="180"
            android:pivotY="150"
            android:pivotX="150"
            android:duration="5000">
    </rotate>

</set>

 

note! ! ! pivotX and pivotY are 150, which is exactly half the width and height of the TextView.

Activity call:

    /**
     *      旋转动画
     * */
    private fun startAni3() {
        //先加载 旋转动画
        val animation = AnimationUtils.loadAnimation(this, R.anim.rotate_ani)
        tv_animator.startAnimation(animation)

        /*
        *       或者
        * */
        val rotateAnimation = RotateAnimation(0F, 180F, 150F, 150F)
        rotateAnimation.fillAfter = true
        rotateAnimation.duration = 5000
        tv_animator.startAnimation(rotateAnimation)
    }

The result of the test is that when the TextView is 300*300 px,

1> Both pivotX and pivotY are 150, and the center of rotation is the center of TextView

1> pivotX and pivotY are both 0, and the center of rotation is the upper left corner of the TextView

Therefore, the conclusion is: the coordinates of the rotating dot are based on the coordinates of the upper left corner (0,0) of the target View.

 

 

【Scale】

Zoom. . . . . .

fromXScale,fromYScale   X Y 方向  缩放起始值
toXScale, toYScale     X Y 方向  缩放结束值
pivotX ,pivotY          X Y 方向  缩放中心值   中心点也是和上面的基准规则一样

The codes are not posted, they are all the same principle. . . . .

 

============ [Multiple animations are played together or in sequence] =============

Play multiple animations simultaneously :

my_toget__animat.xml代码:   多个动画(透明,旋转,缩放)一起
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">

    <alpha android:fromAlpha="1"
           android:toAlpha="0"
           android:duration="5000">
    </alpha>

    <rotate android:fromDegrees="0"
            android:toDegrees="180"
            android:pivotY="150"
            android:pivotX="150"
            android:duration="5000">
    </rotate>

    <scale android:fromXScale="0"
           android:fromYScale="0"
           android:toXScale="1"
           android:toYScale="1"
           android:pivotX="150"
           android:pivotY="150"
           android:duration="5000">
    </scale>

</set>

 

Processing of the view layer: the result of the operation is (transparency, rotation, zoom) by colleagues

private fun animationSet(){
        //加载 
        val animation = AnimationUtils.loadAnimation(this, R.anim.my_toget__animat)
        tv_animator_view.startAnimation(animation)
    }

 

This can be done without the xml type, and can use dynamic code, such as:

private fun animationSet(){
        val rotateAnimation = RotateAnimation(0F, 180F, 150F, 150F)
        val alphaAnimation = AlphaAnimation(1.0F, 0F)
        val scaleAnimation = ScaleAnimation(0F, 1F, 0F, 1F, 150F, 150F)

        //多个动画 放进 AnimationSet 
        val animationSet = AnimationSet(true)
        animationSet.addAnimation(rotateAnimation)
        animationSet.addAnimation(alphaAnimation)
        animationSet.addAnimation(scaleAnimation)
        animationSet.duration = 5000
        tv_animator_view.startAnimation(animationSet)
    }

Set the AnimationSet collection by dynamic code, put the required animation into it, the effect is the same

 

 

Multiple animations are played in sequence :

The idea of ​​sequential playback is to use the delay method in xml to specify the delay execution of the animation through startOffset

such as:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">

    <alpha android:fromAlpha="0"
           android:toAlpha="1"
           android:duration="3000"
           android:fillAfter="true">
    </alpha>

    <!--第2个动画延迟3000毫秒-->
    <rotate
            android:startOffset="3000"
            android:fromDegrees="0"
            android:toDegrees="180"
            android:pivotY="150"
            android:pivotX="150"
            android:duration="3000"
            android:fillAfter="true">
    </rotate>
    
</set>

 

The loading setting usage is the same, so I won’t post it

 

Use code to set the sequence, monitor the completion of the first animation, and then perform the second animation

private fun animationOrder(){
        val rotateAnimation = RotateAnimation(0F, 180F, 150F, 150F)
        rotateAnimation.fillAfter = true
        rotateAnimation.duration = 5000
        rotateAnimation.setAnimationListener(object :Animation.AnimationListener{
            override fun onAnimationRepeat(animation: Animation?) {
                //动画重复
            }

            override fun onAnimationEnd(animation: Animation?) {
                //动画结束
                val alphaAnimation = AlphaAnimation(1.0F, 0F)
                alphaAnimation.fillAfter = true
                alphaAnimation.duration = 5000
                tv_animator_view.startAnimation(alphaAnimation)
            }

            override fun onAnimationStart(animation: Animation?) {
                //动画开始

            }

        })
        tv_animator_view.startAnimation(rotateAnimation)
    }

 

 

=======【layoutAnimation】==========

Act on ViewGroup, specify an animation for a ViewGroup, all of its child elements will have this animation effect when they leave the factory

For example, when RecycleView is specified, each item will have

For example, when ViewGroup is specified, each child View will have

First, create layoutAnimation: anim/ layout_animation.xml

<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
                 android:delay="1"
                 android:animationOrder="random"
                 android:animation="@anim/alpha_ani">

    <!--
            delay: 每个子View时间间隔 如果有多个子view的话,如果设定的动画周期是 duration = 1000毫秒,
                    如果 delay=0.1,则下一个子View 会在100(duration * delay)毫秒执行动画

            animationOrder:子view经常顺序,normal是最前面的先进来,
                                            reverse是最后的先进来
                                            random 正看英文就知道。。。。哈哈

            顺序就是View.getChildView(index)  里面的这个index
    -->
</layoutAnimation>

Create layoutAnimation: anim/ alpha.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:fillAfter="true">

    <!--透明
        fromAlpha:开始时透明度 0.0- 1.0   0.0全透明  1.0不透明
        toAlpha: 结束时透明度 0.0- 1.0
        duration:动画持续时间 单位 毫秒
        fillAfter:动画结束后是否停留在结束位置,true停留
        -->
    <alpha android:fromAlpha="0"
           android:toAlpha="1"
           android:duration="5000"
    >
    </alpha>

</set>

 

Parent layout layout file:

<android.support.constraint.ConstraintLayout
            android:id="@+id/tv_animator_contain"
            android:layout_width="0dp"
            android:layout_height="300px"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            android:layoutAnimation="@anim/layout_animation"
            android:visibility="invisible"
    >

        <TextView
                android:id="@+id/tv_animator_view"
                android:layout_width="300px"
                android:layout_height="300px"
                android:background="@color/color_00a3f3"
                android:text="目标动画1"
                android:textColor="@color/color_7e4513"
                android:gravity="center"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toLeftOf="@id/tv_animator_view2"
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintHorizontal_chainStyle="spread"/>


        <TextView
                android:id="@+id/tv_animator_view2"
                android:layout_width="300px"
                android:layout_height="300px"
                android:background="@color/color_00a3f3"
                android:text="目标动画1"
                android:textColor="@color/color_7e4513"
                android:gravity="center"
                app:layout_constraintLeft_toRightOf="@id/tv_animator_view"
                app:layout_constraintRight_toLeftOf="@id/tv_animator_view3"
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintHorizontal_chainStyle="spread"/>

        <TextView
                android:id="@+id/tv_animator_view3"
                android:layout_width="300px"
                android:layout_height="300px"
                android:background="@color/color_00a3f3"
                android:text="目标动画1"
                android:textColor="@color/color_7e4513"
                android:gravity="center"
                app:layout_constraintLeft_toRightOf="@id/tv_animator_view2"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintHorizontal_chainStyle="spread"/>

    </android.support.constraint.ConstraintLayout>

 

note! !   The  visibility of the parent layout = invisible, when the parent layout becomes visible, the three child views will be displayed

Of course, the form that appears is in the form of animation. . .

Call in code:

private fun layoutAnimation() {
        tv_animator_contain.visibility = View.VISIBLE
    }

Simply display the parent layout, and all child Views will appear with animation effects. . . .

You can also not set the layout in the parent layout, through  LayoutAnimationController

Directly on the code:

private fun layoutAnimation() {
        val loadAnimation = AnimationUtils.loadAnimation(this, R.anim.alpha_ani)
        val animationController = LayoutAnimationController(loadAnimation)
        animationController.delay = 0.1F
        animationController.order = LayoutAnimationController.ORDER_NORMAL
        tv_animator_contain.layoutAnimation = animationController
        tv_animator_contain.visibility = View.VISIBLE
    }

note! ! ! ! ! ! !

The code refers to  alpha_ani.xml , which directly refers to the animation file, not to   layoutAnimation 

 

==================[ Frame Animation ]=========================

First of all, the frame animation is similar to video playback. It displays 26 pictures in one second, and the effect that the naked eye sees is the video.

Frame animation will load all pictures into memory at once, and then display the next picture every time the duration is set. . .

Not recommended! ! ! Because it consumes memory! ! ! ! ! !

First, create a frame animation, which is in the drawable directory. . .

Then select animation-list

 

then 

 

Use in the control:

    /**
     *      帧动画
     * */
    private fun startFrameAni() {
        //先设置
        tv_animator_view.setBackgroundResource(R.drawable.frame_animation)
        //再获取  强转成 AnimationDrawable
        val background = tv_animator_view.background as AnimationDrawable
        //开启动画
        background.start()
    }

Again, if there are too many pictures, it will easily lead to OOM

If you have to use frame animation, you can put all the IDs of the drawable you need into a List

Then write a timer by yourself (for example, use Handler), every few seconds, get the drawable through the ID to display a picture, so as to avoid loading all pictures into memory at once. . . .

All right. . . . . . Here is here

 

 

The next article is written: attribute animation

The above code is no problem in the pro-test,,,, if there is a problem, please leave a message to correct it,,, thank you! ! ! !

 

Guess you like

Origin blog.csdn.net/Leo_Liang_jie/article/details/90752748