转载请标明出处: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位移

布局:

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">

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" />

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" />

动画核心思路 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位移加循环

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

}

}

相关阅读

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。