Android 属性动画常见效果收集

转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/128948795
本文出自【赵彦军的博客】

属性动画往期博客
Android属性动画 AnimatorSet
Android属性动画 ObjectAnimator

文章目录

  • 1、呼吸动画
  • 2、摇晃动画
  • 3、两个view位移
  • 4、两个view位移加循环

1、呼吸动画

在这里插入图片描述

//呼吸动画
fun View.breathAnim(): AnimatorSet {
    val anim1 = ObjectAnimator.ofFloat(this, "scaleX", 1.0f, 0.8f)
    val anim2 = ObjectAnimator.ofFloat(this, "scaleY", 1.0f, 0.8f)
    val sets = AnimatorSet()
    sets.playTogether(anim1, anim2)
    sets.interpolator = LinearInterpolator()
    sets.duration = 800
    anim1.repeatMode = ValueAnimator.REVERSE
    anim2.repeatMode = ValueAnimator.REVERSE
    anim1.repeatCount = ValueAnimator.INFINITE
    anim2.repeatCount = ValueAnimator.INFINITE
    sets.start()
    return sets
}

使用:

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding

    private var breathAnim: AnimatorSet? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        //呼吸动画
        breathAnim = binding.breath.breathAnim()
    }

    override fun onDestroy() {
        super.onDestroy()
        breathAnim?.cancel()
    }
}

2、摇晃动画

在这里插入图片描述

//摇晃动画
fun View.shake(): AnimatorSet {
    val animatorX = ObjectAnimator.ofFloat(this, "scaleX", 1f, 1.08f, 1f)
    val animatorY = ObjectAnimator.ofFloat(this, "scaleY", 1f, 1.08f, 1f)
    val rotation = ObjectAnimator.ofFloat(this, "rotation", 0f, 15f, 0f, -15f, 0f, 12f, 0f, -12f, 0f, 9f, 0f, -9f, 0f, 6f, 0f, -6f, 0f, 3f, 0f, -3f, 0f)
    val animatorSet = AnimatorSet()
    animatorSet.playTogether(animatorX, animatorY, rotation)
    animatorSet.duration = 600
    animatorSet.interpolator = LinearInterpolator()
    animatorSet.startDelay = 1200
    var cancel = false
    animatorSet.addListener(object : AnimatorListenerAdapter() {
        override fun onAnimationEnd(animation: Animator) {
            super.onAnimationEnd(animation)
            if (!cancel) {
                animatorSet.start()
            }
        }

        override fun onAnimationCancel(animation: Animator?) {
            super.onAnimationCancel(animation)
            cancel = true
        }
    })
    animatorSet.start()
    return animatorSet
}

使用:

package com.example.myapplication

import android.animation.AnimatorSet
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.example.myapplication.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding
    private var shakeAnim: AnimatorSet? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        
        //抖动动画
        shakeAnim = binding.shake.shake()
    }

    override fun onDestroy() {
        super.onDestroy()
        shakeAnim?.cancel()
    }
}

3、两个view位移

Android 属性动画常见效果收集_第1张图片

布局:

<?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"
    android:clipChildren="true"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/view1"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:layout_marginHorizontal="20dp"
        android:layout_marginTop="20dp"
        android:background="#f00"
        android:gravity="center"
        android:textColor="@color/white"
        android:translationZ="10dp"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/view2"
        android:layout_width="100dp"
        android:layout_height="60dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

动画核心思路
Android 属性动画常见效果收集_第2张图片
1、分别计算view1、view2 中心点的 x , y 坐标,计算方式使用 view.getLocationInWindow(location)
2、计算view1 到 view2 的 x、y 轴的距离
3、最后加上缩放,透明度动画即可完美实现
4、最后一点也是最重要的,view1 在平移过程中会被 view2 遮挡,需要在布局中抬高 view1 的层级,使用 android:translationZ="10dp"

使用:

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        binding.shake.setOnClickListener {
            startCloseAnimation(binding.view1, binding.view2)
        }
    }

    private fun startCloseAnimation(v1: View, v2: View) {
        val offset = getOffSet(v1, v2)
        val transX = offset[0]
        val transY = offset[1]

        val scaleX = ObjectAnimator.ofFloat(v1, "scaleX", 1f, 0f)
        val scaleY = ObjectAnimator.ofFloat(v1, "scaleY", 1f, 0f)
        val alpha = ObjectAnimator.ofFloat(v1, "alpha", 1f, 0.3f)
        val translationX = ObjectAnimator.ofFloat(v1, "translationX", transX.toFloat())
        val translationY = ObjectAnimator.ofFloat(v1, "translationY", transY.toFloat())

        val animatorSet = AnimatorSet()
        animatorSet.let {
            it.playTogether(scaleX, scaleY, translationX, translationY, alpha)
            it.duration = 800
            it.interpolator = AccelerateDecelerateInterpolator()
            it.addListener(object : AnimatorListenerAdapter() {
                override fun onAnimationEnd(animation: Animator) {
                    super.onAnimationEnd(animation)
                    v1.visibility = View.GONE
                }
            })
            it.start()
        }
    }

    //计算两个view,x/y坐标的相对距离
    private fun getOffSet(v1: View, v2: View): IntArray {
        //获取v1的坐标
        val location1 = IntArray(2)
        v1.getLocationInWindow(location1)
        //修正v1的位置为中心位置
        location1[0] = location1[0] + v1.width / 2
        location1[1] = location1[1] + v1.height / 2

        //获取v2的坐标
        val location2 = IntArray(2)
        v2.getLocationInWindow(location2)
        //修正v2的位置为中心位置
        location2[0] = location2[0] + v2.width / 2
        location2[1] = location2[1] + v2.height / 2

        val result = IntArray(2)
        result[0] = location2[0] - location1[0]
        result[1] = location2[1] - location1[1]
        return result
    }
}

4、两个view位移加循环

Android 属性动画常见效果收集_第3张图片

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            //这一句很关键,提高view1的层级。否则会被其他view遮挡
            binding.view1.z = 100f
        }
        binding.view2.setOnClickListener {
            startCloseAnimation(binding.view1, binding.view2)
        }
    }

    private fun startCloseAnimation(v1: View, v2: View) {
        val offset = getOffSet(v1, v2)
        val transX = offset[0]
        val transY = offset[1]

        val scaleX = ObjectAnimator.ofFloat(v1, "scaleX", 1f, 0.1f)
        val scaleY = ObjectAnimator.ofFloat(v1, "scaleY", 1f, 0.1f)
        val alpha = ObjectAnimator.ofFloat(v1, "alpha", 1f, 0.3f)
        val translationX = ObjectAnimator.ofFloat(v1, "translationX", transX.toFloat())
        val translationY = ObjectAnimator.ofFloat(v1, "translationY", transY.toFloat())

        scaleX.repeatCount = ObjectAnimator.INFINITE
        scaleX.repeatMode = ObjectAnimator.REVERSE

        scaleY.repeatCount = ObjectAnimator.INFINITE
        scaleY.repeatMode = ObjectAnimator.REVERSE

        alpha.repeatCount = ObjectAnimator.INFINITE
        alpha.repeatMode = ObjectAnimator.REVERSE

        translationX.repeatCount = ObjectAnimator.INFINITE
        translationX.repeatMode = ObjectAnimator.REVERSE

        translationY.repeatCount = ObjectAnimator.INFINITE
        translationY.repeatMode = ObjectAnimator.REVERSE

        val animatorSet = AnimatorSet()
        animatorSet.let {
            it.playTogether(scaleX, scaleY, translationX, translationY, alpha)
            it.duration = 1000
            it.interpolator = AccelerateDecelerateInterpolator()
            it.start()
        }
    }

    //计算两个view,x/y坐标的相对距离
    private fun getOffSet(v1: View, v2: View): IntArray {
        //获取v1的坐标
        val location1 = IntArray(2)
        v1.getLocationInWindow(location1)
        //修正v1的位置为中心位置
        location1[0] = location1[0] + v1.width / 2
        location1[1] = location1[1] + v1.height / 2

        //获取v2的坐标
        val location2 = IntArray(2)
        v2.getLocationInWindow(location2)
        //修正v2的位置为中心位置
        location2[0] = location2[0] + v2.width / 2
        location2[1] = location2[1] + v2.height / 2

        val result = IntArray(2)
        result[0] = location2[0] - location1[0]
        result[1] = location2[1] - location1[1]
        return result
    }
}

你可能感兴趣的:(属性动画,android,动画,AnimatorSet)