转载请标明出处: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" />
动画核心思路 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
}
}
相关阅读
发表评论