利用Android实现一种点赞动画效果的全过程
ChenYhong 人气:0前言
最近有个需求,需要仿照公司的H5实现一个游戏助手,其中一个点赞的按钮有动画效果,如下图:
分析一下这个动画,点击按钮后,拇指首先有个缩放的效果,然后有5个拇指朝不同的方向移动,其中部分有放大的效果。
点击后的缩放效果
本文通过ScaleAnimation
实现缩放效果,代码如下:
private fun playThumbUpScaleAnimator() { // x、y轴方向都从1倍放大到2倍,以控件的中心为原点进行缩放 ScaleAnimation(1f, 2f, 1f, 2f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f).run { // 先取消控件当前的动画效果(重复点击时) view.clearAnimation() // 设置动画的持续时间 duration = 300 // 开始播放动画 view.startAnimation(this) } }
拇指的散开效果
有5个拇指分别往不同的方向移动,本文通过动态添加View
,并对View
设置动画来实现。可以看到在移动的同时还有缩放的效果,所以需要同时播放几个动画。
本文通过ValueAnimator
和AnimatorSet
来实现该效果,代码如图:
// 此数组控制动画的效果 // 第一个参数控制X轴移动距离 // 第二个参数控制Y轴移动距离 // 第三个参数控制缩放的倍数(基于原大小) val animatorConfig: ArrayList<ArrayList<Float>> = arrayListOf( arrayListOf(-160f, 150f, 1f), arrayListOf(80f, 130f, 1.1f), arrayListOf(-120f, -170f, 1.3f), arrayListOf(80f, -130f, 1f), arrayListOf(-20f, -80f, 0.8f)) private fun playDiffusionAnimator() { for (index in 0 until 5) { binding.root.run { if (this is ViewGroup) { // 创建控件 val ivThumbUp = AppCompatImageView(context) ivThumbUp.setImageResource(R.drawable.icon_thumb_up) // 设置与原控件一样的大小 ivThumbUp.layoutParams = FrameLayout.LayoutParams(DensityUtil.dp2Px(25), DensityUtil.dp2Px(25)) // 先设置为全透明 ivThumbUp.alpha = 0f addView(ivThumbUp) // 设置与原控件一样的位置 ivThumbUp.x = binding.ivThumbUp.x ivThumbUp.y = binding.ivThumbUp.y AnimatorSet().apply { // 设置动画集开始播放前的延迟 startDelay = 330L + index * 50L // 设置动画监听 addListener(object : Animator.AnimatorListener { override fun onAnimationStart(animation: Animator) { // 开始播放时把控件设置为不透明 ivThumbUp.alpha = 1f } override fun onAnimationEnd(animation: Animator) { // 播放结束后再次设置为透明,并从根布局中移除 ivThumbUp.alpha = 0f ivThumbUp.clearAnimation() ivThumbUp.post { removeView(ivThumbUp) } } override fun onAnimationCancel(animation: Animator) {} override fun onAnimationRepeat(animation: Animator) {} }) // 设置三个动画同时播放 playTogether( // 缩放动画 ValueAnimator.ofFloat(1f, animatorConfig[index][2]).apply { duration = 700 // 设置插值器,速度一开始快,快结束时减慢 interpolator = DecelerateInterpolator() addUpdateListener { values -> (values.animatedValue as Float).let { value -> ivThumbUp.scaleX = value ivThumbUp.scaleY = value } } }, // X轴的移动动画 ValueAnimator.ofFloat(ivThumbUp.x, ivThumbUp.x + animatorConfig[index][0]).apply { duration = 700 interpolator = DecelerateInterpolator() addUpdateListener { values -> ivThumbUp.x = values.animatedValue as Float } }, // Y轴的移动动画 ValueAnimator.ofFloat(ivThumbUp.y, ivThumbUp.y + animatorConfig[index][1]).apply { duration = 700 interpolator = DecelerateInterpolator() addUpdateListener { values -> ivThumbUp.y = values.animatedValue as Float } }) }.start() } } } }
示例
整合之后做了个示例Demo,完整代码如下:
class AnimatorSetExampleActivity : BaseGestureDetectorActivity() { private lateinit var binding: LayoutAnimatorsetExampleActivityBinding private val animatorConfig: ArrayList<java.util.ArrayList<Float>> = arrayListOf( arrayListOf(-160f, 150f, 1f), arrayListOf(80f, 130f, 1.1f), arrayListOf(-120f, -170f, 1.3f), arrayListOf(80f, -130f, 1f), arrayListOf(-20f, -80f, 0.8f)) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = DataBindingUtil.setContentView(this, R.layout.layout_animatorset_example_activity) binding.ivThumbUp.setOnClickListener { playThumbUpScaleAnimator() playDiffusionAnimator() } } private fun playThumbUpScaleAnimator() { // x,y轴方向都从1倍放大到2倍,以控件的中心为原点进行缩放 ScaleAnimation(1f, 2f, 1f, 2f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f).run { // 先取消控件当前的动画效果(重复点击时) binding.ivThumbUp.clearAnimation() // 设置动画的持续时间 duration = 300 // 开始播放动画 binding.ivThumbUp.startAnimation(this) } } private fun playDiffusionAnimator() { for (index in 0 until 5) { binding.root.run { if (this is ViewGroup) { // 创建控件 val ivThumbUp = AppCompatImageView(context) ivThumbUp.setImageResource(R.drawable.icon_thumb_up) // 设置与原控件一样的大小 ivThumbUp.layoutParams = FrameLayout.LayoutParams(DensityUtil.dp2Px(25), DensityUtil.dp2Px(25)) // 先设置为全透明 ivThumbUp.alpha = 0f addView(ivThumbUp) // 设置与原控件一样的位置 ivThumbUp.x = binding.ivThumbUp.x ivThumbUp.y = binding.ivThumbUp.y AnimatorSet().apply { // 设置动画集开始播放前的延迟 startDelay = 330L + index * 50L // 设置动画监听 addListener(object : Animator.AnimatorListener { override fun onAnimationStart(animation: Animator) { // 开始播放时把控件设置为不透明 ivThumbUp.alpha = 1f } override fun onAnimationEnd(animation: Animator) { // 播放结束后再次设置为透明,并从根布局中移除 ivThumbUp.alpha = 0f ivThumbUp.clearAnimation() ivThumbUp.post { removeView(ivThumbUp) } } override fun onAnimationCancel(animation: Animator) {} override fun onAnimationRepeat(animation: Animator) {} }) // 设置三个动画同时播放 playTogether( // 缩放动画 ValueAnimator.ofFloat(1f, animatorConfig[index][2]).apply { duration = 700 // 设置插值器,速度一开始快,快结束时减缓 interpolator = DecelerateInterpolator() addUpdateListener { values -> (values.animatedValue as Float).let { value -> ivThumbUp.scaleX = value ivThumbUp.scaleY = value } } }, // Y轴的移动动画 ValueAnimator.ofFloat(ivThumbUp.x, ivThumbUp.x + animatorConfig[index][0]).apply { duration = 700 interpolator = DecelerateInterpolator() addUpdateListener { values -> ivThumbUp.x = values.animatedValue as Float } }, // X轴的移动动画 ValueAnimator.ofFloat(ivThumbUp.y, ivThumbUp.y + animatorConfig[index][1]).apply { duration = 700 interpolator = DecelerateInterpolator() addUpdateListener { values -> ivThumbUp.y = values.animatedValue as Float } }) }.start() } } } } }
效果如图:
个人感觉还原度还是可以的哈哈。
总结
加载全部内容