Android animation basics: View animation

Preface

The object of View animation is View, which supports 4 kinds of animation effects, which are translation animation, zoom animation, rotation animation and transparency animation, corresponding to the four subcategories of Animation: TranslateAnimation, ScaleAnimation, RotateAnimation and AlphaAnimation.

Panning

private fun translateAnimEx(btn: Button){
        btn.text="平移动画"
        // xml
        val transAnimation = AnimationUtils.loadAnimation(this, R.anim.anim_translate_ex)
        transAnimation.duration = 3000
        btn.startAnimation(transAnimation)
        // 代码
        val transAnimation=TranslateAnimation(0f,180f,0f,180f)
        transAnimation.duration = 3000
        btn.startAnimation(transAnimation)
    }
anim_translate_ex.xml文件
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXDelta="0"
    android:fromYDelta="0"
    android:toXDelta="180"
    android:toYDelta="180" />

effect:

Zoom animation

private fun scaleAnimEx(btn: Button){
        btn.text="缩放动画"

        // xml
        val scaleAnimation = AnimationUtils.loadAnimation(this, R.anim.anim_scale_ex)
        scaleAnimation.duration = 3000
        btn.startAnimation(scaleAnimation)

        // 代码
        val scaleAnimation=ScaleAnimation(0f,120f,0f,120f,
               50f, 50f)
        scaleAnimation.duration = 3000
        btn.startAnimation(scaleAnimation)
    }
anim_scale_ex.xml
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXScale="0"
    android:toXScale="20"
    android:fromYScale="0"
    android:toYScale="20"
    android:pivotX="50"
    android:pivotY="50"/>

effect:

Rotate animation

 private fun rotateAnimEx(btn: Button){
        btn.text="旋转动画"

        // xml
        val rotateAnimation = AnimationUtils.loadAnimation(this, R.anim.anim_rotate_ex)
        rotateAnimation.duration = 3000
        btn.startAnimation(rotateAnimation)

        // 代码
        val rotateAnimation=RotateAnimation(0f,360f,100f,100f)
        rotateAnimation.duration = 3000
        btn.startAnimation(rotateAnimation)
    }
anim_rotate_ex.xml
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromDegrees="0"
    android:pivotX="100"
    android:pivotY="100"
    android:toDegrees="360" />

effect

Transparency animation

private fun alphaAnimEx(btn: Button){
        btn.text="透明动画"
        // xml
        val alphaAnimation = AnimationUtils.loadAnimation(this, R.anim.anim_alpha_ex)
        alphaAnimation.duration=3000
        btn.startAnimation(alphaAnimation)

        // 代码
        val alphaAnimation = AlphaAnimation(0f, 1f)
        alphaAnimation.duration = 3000

        btn.startAnimation(alphaAnimation)
    }
anim_alpha_ex.xml
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromAlpha="0"
    android:toAlpha="1" />

effect

Animation collection

private fun setAnimEx(btn: Button){
        // xml
        val setAnimation = AnimationUtils.loadAnimation(this, R.anim.animation_set)
        setAnimation.duration = 3000
        btn.startAnimation(setAnimation)

        // 代码
        val rotateAnimation=RotateAnimation(0f,360f)
        val transAnimation=TranslateAnimation(0f,180f,0f,180f)

        val setAnimation=AnimationSet(false)
        setAnimation.addAnimation(rotateAnimation)
        setAnimation.addAnimation(transAnimation)

        setAnimation.duration = 350
        setAnimation.fillAfter=true
        setAnimation.interpolator=LinearInterpolator()
        setAnimation.zAdjustment=AnimationSet.ZORDER_NORMAL
        btn.startAnimation(setAnimation)
    }
animation_set.xml
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:fillAfter="true"
    android:interpolator="@android:anim/linear_interpolator"
    android:duration="350"
    android:zAdjustment="normal">

    <translate

        android:fromXDelta="0"
        android:fromYDelta="0"
        android:toXDelta="100"
        android:toYDelta="100" />

    <rotate
        android:duration="100"
        android:fromDegrees="0"
        android:toDegrees="360" />
</set>

Animation xml related attributes

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    //动画持续的时间
    android:duration="{int}"
    //动画结束以后View是否停留在结束位置,true表示View停留在结束位置,false则不停留
    android:fillAfter="{true|false}"
    //动画结束以后View是否停留在开始位置,true表示View停留在结束位置,false则不停留
    android:fillBefore="{true|false}"
    // 表示集合中的动画是否和集合共享同一个插值器
    android:shareInterpolator="{true|false}"
    // 重复模式
    android:repeatMode="{restart|reverse}"
    // 延时开始动画
    android:startOffset="{int}"
    // 设置插值器,
    android:interpolator="@{package:}anim/interpolator_resource">

    <rotate
        //旋转开始的角度
        android:fromDegrees="float"
        //旋转的**轴点**的x坐标
        android:pivotX="float"
        // 旋转的**轴点**的y坐标
        android:pivotY="float"
        // 旋转结束的角度
        android:toDegrees="float" />

    <alpha
        //表示透明度的起始值
        android:fromAlpha="float"
        //表示透明度的结束值
        android:toAlpha="float" />
    <scale
        //水平方向缩放的起始值
        android:fromXScale="float"
        //竖直方向缩放的起始值
        android:fromYScale="float"
        //旋转的**轴点**的x坐标
        android:pivotX="float"
        // 旋转的**轴点**的y坐标
        android:pivotY="float"
        //水平方向缩放的结束值
        android:toXScale="float"
        //竖直方向缩放的结束值
        android:toYScale="float" />
    <translate
        //表示x的起始值
        android:fromXDelta="float"
        //表示y的起始值
        android:fromYDelta="float"
        //水平方向缩放的结束值
        android:toXDelta="float"
        // 表示y的结束值
        android:toYDelta="float" />

</set>

Custom animation

You only need to inherit the abstract class of Animation, then rewrite its initialize and applyTransformation methods, do some initialization work in the initialize method, and perform the corresponding matrix transformation in applyTransformation. In many cases, you need to use Camera to simplify the process of matrix transformation.

Example: 3D rotation

// 自定义View 动画
    private fun animatonView() {
        val rotate3DAnimation = Rotate3DAnimation(0f, 360f, 30f, 180f, true, 6f)
        rotate3DAnimation.interpolator = AccelerateDecelerateInterpolator()
        rotate3DAnimation.fillAfter = true
        rotate3DAnimation.duration = 3500
        btn_anim_set.startAnimation(rotate3DAnimation)
    }


class Rotate3DAnimation : Animation {


    private var mFromDegree: Float
    private var mToDegree: Float
    private var mCenterX: Float
    private var mCenterY: Float
    private var mDepthZ: Float
    private var mReverse: Boolean
    private lateinit var mCamera: Camera

    constructor(mFromDegree: Float, mToDegree: Float, mCenterX: Float,mCenterY: Float,   mReverse: Boolean, mDepthZ: Float) : super() {
        this.mFromDegree = mFromDegree
        this.mCenterY = mCenterY
        this.mCenterX = mCenterX
        this.mToDegree = mToDegree
        this.mReverse = mReverse
        this.mDepthZ = mDepthZ
    }


    // 初始化
    override fun initialize(width: Int, height: Int, parentWidth: Int, parentHeight: Int) {
        super.initialize(width, height, parentWidth, parentHeight)
        this.mCamera = Camera()
    }

    // 矩阵变化
    override fun applyTransformation(interpolatedTime: Float, t: Transformation?) {
        super.applyTransformation(interpolatedTime, t)
        var fromDegree=mFromDegree
        var degree=fromDegree+(mToDegree-mFromDegree)*interpolatedTime

        var centerX=mCenterX
        var centerY=mCenterY

        val  camera=mCamera
        val matrix=t?.matrix
        //将当前的摄像头位置保存下来,以便变换进行完成后恢复成原位
        camera.save()
        // camera.translate,这个方法接受3个参数,分别是x,y,z三个轴的偏移量,我们这里只将z轴进行了偏移
        if (mReverse){
            // z的偏移会越来越大。这就会形成这样一个效果,view从近到远
            camera.translate(0f,0f,mDepthZ*interpolatedTime)
        }else{
            // z的偏移会越来越小。这就会形成这样一个效果,我们的View从一个很远的地方向我们移过来,越来越近,
                // 最终移到了我们的窗口上面
            camera.translate(0f,0f,mDepthZ*(1f-interpolatedTime))
        }
//        View加上旋转效果,在移动的过程中,视图还会移Y轴为中心进行旋转
        camera.rotateY(degree)
//        将我们刚才定义的一系列变换应用到变换矩阵上面,调用完这句之后,我们就可以将camera的位置恢复了,以便下一次再使用
        camera.getMatrix(matrix)
        // camera位置恢复
        camera.restore()
// 以View的中心点为旋转中心,如果不加这两句,就是以(0,0)点为旋转中心
        matrix?.preTranslate(-centerX,-centerY)
        matrix?.postTranslate(centerX,centerY)
    }
}

effect:

VIew animation principle

Each time a view is drawn, the drawChild function in the ViewGroup where the View is located obtains the Transformation value of the View's Animation, and then calls canvas.contact(transformToApply.getMatrix()) to complete the animation frame through matrix operations. If the animation is not completed, continue to call the invalidate() function to start the next drawing to drive the animation, so as to complete the drawing of the entire animation.
 

Guess you like

Origin blog.csdn.net/xufei5789651/article/details/112723615