You have to believe in yourself. That's the secret of success.

之前的QQ版本里面有个大表情的动画很炫酷,之前就想着怎么实现的。最近看了DynamicAnimation,发现利用它很容易实现类似效果,自己最近也在看Kotlin,因此就用Kotlin写个demo练练手。

实现效果

等我实现了效果,发现QQ已经把该功能去掉了T_T。原版的效果看不到了,直接放我实现的效果。

在这里插入图片描述

实现原理

窗口的左右抖动效果

借助SpringAnimation 可以实现,顾名思义该动画库能实现弹簧般的抖动效果。与弹簧相关的两个重要物理属性分别是Damping ratio(阻尼比)和Stiffness(刚性)。

Damping ratio(阻尼比)

阻尼比描述了弹簧振荡过程中逐渐减小的速度。 通过阻尼比,可以调整振荡从一次反弹到下一次反弹的衰减速度。

官方用法示例:

findViewById(R.id.imageView).also { img ->

SpringAnimation(img, DynamicAnimation.TRANSLATION_Y).apply {

//Setting the damping ratio to create a low bouncing effect.

spring.dampingRatio = SpringForce.DAMPING_RATIO_LOW_BOUNCY

}

}

动画库已经提供了四种类型的阻尼比,官方也提供了相对应的效果图

DAMPING_RATIO_HIGH_BOUNCY

在这里插入图片描述

DAMPING_RATIO_MEDIUM_BOUNCY

在这里插入图片描述

DAMPING_RATIO_LOW_BOUNCY

在这里插入图片描述

DAMPING_RATIO_NO_BOUNCY

在这里插入图片描述

Stiffness(刚性)

刚性指弹簧产生形变时,产生的弹力大小。相应的系统也提供了四种值。

STIFFNESS_HIGH

STIFFNESS_MEDIUM

STIFFNESS_LOW

STIFFNESS_VERY_LOW

Stiffness的值越大,弹簧动画看起来的抖动也就越不明显,就像我们施加相同的力给粗细不同的铁丝弹簧,施加的力取消后,越粗的弹簧刚性越大,它的抖动就没有细的弹簧明显。

官方用法示例:

findViewById(R.id.imageView).also { img ->

SpringAnimation(img, DynamicAnimation.TRANSLATION_Y).apply {

//Setting the spring with a low stiffness.

spring.stiffness = SpringForce.STIFFNESS_LOW

}

}

SpringForce自定义弹簧动画属性

如果想将Damping ratio/Stiffness 应用在多个弹簧动画中,可以通过SpringForce 来设置。

SpringForce force = new SpringForce();

force.setDampingRatio(DAMPING_RATIO_LOW_BOUNCY).setStiffness(STIFFNESS_LOW);

setSpring(force);

有了上面的知识,可以很容易的实现窗口左右抖动的效果。

private fun startWindowAnimation() {

val springAnimation = createSpringAnimation(window.decorView, SpringAnimation.TRANSLATION_X);

springAnimation.start();

}

fun createSpringAnimation(view: View, property: DynamicAnimation.ViewProperty): SpringAnimation {

val animation = SpringAnimation(view, property)

animation.setStartVelocity(4000f);

val spring = SpringForce(0f)

spring.stiffness = SpringForce.STIFFNESS_MEDIUM

spring.dampingRatio = SpringForce.DAMPING_RATIO_HIGH_BOUNCY

animation.spring = spring

animation.setMinimumVisibleChange(DynamicAnimation.MIN_VISIBLE_CHANGE_PIXELS)

return animation

}

在这里插入图片描述

弹球动画

弹球动画比较麻烦点,拆分成三个步骤。

动态添加view

每点击一次button,就动态添加一个弹球view,然后在表情下落时我们添加一个变淡的动画,在动画结束时在将该view删除掉。

X轴上的动画

弹球的动画拆分成X轴跟Y轴,在分别实现以此来降低处理难度。弹球在X轴没有重力影响,只有空气阻力跟碰撞引起的速度衰减,因此很容易通过FlingAnimation动画来模拟,为了进一步简化操作,当弹球碰撞到左右屏幕边缘时,只是将速度取反,不考虑碰撞损失的速度。

FlingAnimation动画可以通过setFriction方法设置一个速度衰减因子,通过该值就可以模拟处X轴受到的空气阻力。

private fun startBallAnimation(movingView: View) {

val flingXAnimation = createFlingAnimation(movingView, DynamicAnimation.TRANSLATION_X);

flingXAnimation.addUpdateListener { animation, value, velocity ->

if (velocity > 0 && movingView.x > screenW - movingView.width) {

flingXAnimation.setStartVelocity(-Math.abs(velocity))

} else if (velocity < 0 && movingView.x < 0) {

flingXAnimation.setStartVelocity(Math.abs(velocity))

}

animation.start()

}

flingXAnimation.setFriction(0.2f)

flingXAnimation.start();

}

fun createFlingAnimation(view: View, property: DynamicAnimation.ViewProperty): FlingAnimation {

val animation = FlingAnimation(view, property)

animation.setStartVelocity(-3000f).setFriction(0.01f)

animation.setMinimumVisibleChange(DynamicAnimation.MIN_VISIBLE_CHANGE_PIXELS)

return animation

}

在这里插入图片描述

Y轴上的动画

Y轴上的动画继续分成两个部分,初次上抛时通过FlingAnimation来模拟,当弹球碰到屏幕的顶端后,转换成属性动画,先取消掉Y轴上的FlingAnimation,在通过给属性动画设置BounceInterpolator插值器来模拟,同时也设置上变淡的动画。在属性动画结束时移除掉弹球。

private fun startBallAnimation(movingView: View) {

//X轴方向的动画

val flingXAnimation = createFlingAnimation(movingView, DynamicAnimation.TRANSLATION_X);

flingXAnimation.addUpdateListener { animation, value, velocity ->

if (velocity > 0 && movingView.x > screenW - movingView.width) {

flingXAnimation.setStartVelocity(-Math.abs(velocity))

} else if (velocity < 0 && movingView.x < 0) {

flingXAnimation.setStartVelocity(Math.abs(velocity))

}

animation.start()

}

flingXAnimation.setFriction(0.2f)

flingXAnimation.start();

//Y轴方向的动画

val flingYAnimation = createFlingAnimation(movingView, DynamicAnimation.TRANSLATION_Y);

flingYAnimation.addUpdateListener { animation, value, velocity ->

if (velocity < 0 && movingView.y < 0) {

flingYAnimation.setStartVelocity(Math.abs(velocity)).setFriction(0.3f)

} else if (velocity > 0) {

flingYAnimation.cancel();

val holder1 = PropertyValuesHolder.ofFloat(View.ALPHA, 1f, 1f, 0f)

val holder2 = PropertyValuesHolder.ofFloat(

View.Y,

movingView.getY(),

(getScreenHeight(this) - 200 - movingView.height).toFloat()

)

val animator = ObjectAnimator.ofPropertyValuesHolder(movingView, holder1, holder2)

animator.setDuration(3000);

val bounceInterpolator = BounceInterpolator()

animator.setInterpolator(bounceInterpolator);

animator.addListener(object : AnimatorListenerAdapter() {

override fun onAnimationEnd(animation: Animator?) {

super.onAnimationEnd(animation)

rootView?.removeView(movingView)

}

})

animator.start()

}

}

flingYAnimation.start();

}

fun createFlingAnimation(view: View, property: DynamicAnimation.ViewProperty): FlingAnimation {

val animation = FlingAnimation(view, property)

animation.setStartVelocity(-3000f).setFriction(0.01f)

animation.setMinimumVisibleChange(DynamicAnimation.MIN_VISIBLE_CHANGE_PIXELS)

return animation

}

通过以上步骤,就实现了弹球效果。

完整代码点击这里

总结

最近刚在学习kotlin,demo代码看起来结构不太清晰,有疑问或者更好的实现方案欢迎交流。

android弹球动画,FlingAnimation/SpringAnimation实现弹球动画相关推荐

  1. Android 利用属ObjectAnimator,AnimatorSet性动画绘制一个弹球,加速下落,到底部时挤压,然后减速上弹...

    属性动画主要的几个类介绍: 1.ValueAnimator:这个类提供了一个简单的计时引擎运行动画动画计算值和设置目标对象.注意:使用该类时一般都是用:ObjectAnimator,而基于Object ...

  2. Simulink学习——弹球仿真三维动画模型(Simulink3D演示动画学习01)

    前有一期我们学习了如何进行物理世界的简单建模仿真,如弹球仿真 https://onebigsoap.blog.csdn.net/article/details/108503788 ,其中可以看到弹球的 ...

  3. android 弹性动画,Android开发SpringAnimation实现弹性动画

    新更新了一个叫做DynamicAnimation(动力学动画??)的类,其中他有一个子类叫做SpringAnimation,官方文档是这样说的: ··· ··· 粗略的翻译一下: 这个类是基于物理学动 ...

  4. 让View具有减速效果的动画——FlingAnimation

    Android动画和Transition系列文章 初识属性动画--使用Animator创建动画 再谈属性动画--介绍以及自定义Interpolator插值器 三谈属性动画--Keyframe以及Vie ...

  5. Android 动画之View动画效果和Activity切换动画效果

    View动画效果: 1.>>Tween动画 通过对View的内容进行一系列的图形变换(平移.缩放.旋转.透明度变换)实现动画效果,补间动画需要使用<set>节点作为根节点,子节 ...

  6. android ui动画效果怎么做,AndroidUI 布局动画-为列表添加布局动画效果

    新建一个Android project ,使MainActivity 继承自 ListActivity: public class MainActivity extends ListActivity ...

  7. android 中间按钮突出,Android 实现 按钮从两边移到中间动画效果

    Android 实现 按钮从两边移到中间动画效果html package org.shuxiang.test; import android.app.Activity; import android. ...

  8. [android] 练习样式主题自定义activity切换动画

    主要练习了自定义样式和主题,继承android系统默认的样式并修改,练习xml定义淡入淡出动画 anim/fade_in.xml <?xml version="1.0" en ...

  9. Android Activity和Fragment的转场动画

    Activity转场动画 Activity的转场动画是通过overridePendingTransition(int enterAnim, int exitAnim)实现的. 这个方法是API Lev ...

  10. Android View体系(三)属性动画

    上一篇文章讲了View滑动的六种方法,其中一种是使用动画,这篇文章我们来讲一讲动画的其中一种:属性动画. 1.android视图动画和属性动画 视图动画我们都了解,它提供了AlphaAnimation ...

最新文章

  1. 使用MySQL命令行修改密码
  2. Android方法调用实体类的值,React Native调用Android原生方法和传值
  3. 带拦截器配置的 struts.xml文件
  4. Prism Training Kit 4.0
  5. Spring配置AOP切入点execution详解
  6. ES6/02/创建对象,构造函数和原型,原型和原型链,this指向,类,ES5新增的方法,数组方法,回调函数,ES5新增的字符串方法,ES5中新增的对象方法
  7. 【Anychat】理解POCO
  8. JNI_OnLoad
  9. memcached安装部署及启动错误排查
  10. CSS中单位rem的使用说明
  11. JS实现PDF合并功能
  12. 正常高、大地高、海拔高的测绘概念
  13. 关于爬取猫眼电影的口碑评分和累计票房的尝试
  14. 云计算学习网站都有哪些?学习云计算的方法
  15. python xml 创建多个同名子节点_果粉有福了!5分钟学会用Python统计自己最爱听的音乐...
  16. CNN和机器学习算法性能测试
  17. Excel线性回归分析(高尔顿数据集;Anscombe四重奏数据集)
  18. JAVA 网络聊天程序设计与实现(附关键代码) 可群聊私聊发送图片
  19. Java Hutool 汉字转拼音码
  20. 百度云服务器最新活动,最新百度云服务器活动 11元购半年

热门文章

  1. 新手SEO篇之外链建设与查询
  2. excel超链接无法打开服务器文件,excle链接的未打开 | excel超链接打不开,超链接后点击出现无法打开指定的文件,求高手解决...
  3. Office 2010/2007 简繁体转换按钮不见了?
  4. 推动服务网格社区前进
  5. 凸优化学习(一)凸集与凸函数、凸优化问题
  6. sizeof 32位和64位操作系统的区别
  7. 2020.9.19hive函数和自定义UDF函数
  8. 破血伐木,千里追踪,梦幻奇游新法诀体验
  9. 最详细教程:Zotero和Better BibTeX安装,以及如何在R markdown中引用文献
  10. CSUOJ 1256 天朝的单行道(最短路)