当前位置: 首页 > news >正文

Android动画

/res/anim/下存放定义补间动画的xml文件

/res/animator/下存放定义属性动画的xml文件

ImageDecoder

Android9引入了Image Decoder,提供了更强大的图片解码支持,可以解码PNG、JPEG等静态态图片,也能直接解码GIF、WEBP等动画图片。
Android9新增了支持HEIF格式,这种压缩格式具有超高的压缩比,相较JPEG格式,其文件大小可以压缩到只有其一半,且可保证近似的图像质量。
当使用ImageDecoder解码GIF、WEBP等动画图片时,程序将会返回一个AnimatedImageDrawable
(Android9新增的API)对象,调用AnimatedImageDrawable对象的start()方法开始执行动画。

帧动画

帧动画是一个Drawable对象:AnimationDrawable,使用<animation-list.../>标签来定义逐帧动画drawable资源,其中使用<item.../>子元素定义动画的各帧,并指定各帧的持续时间,使用android:oneshot设置是否只播放一次。然后把帧动画对象设置给ImageView的source或background。AnimationDrawable代表的动画默认是不播放的,必须在程序中调用start方法播放动画。

补间动画

补间(Tween)动画,只需指定三个必要信息:动画开始帧信息、动画结束帧信息、动画的持续时间,无须"逐一"定义动画过程中的每一帧,而动画变化的"中间帧"由系统计算并补齐,或者叫补帧动画。

补间动画可以分为两大类:视图补间动画(View Animation)和属性补间动画(Property Animation)。

(视图)补间动画

视图动画是通过XML文件或代码定义动画效果,作用于视图(View)的属性上,如位置、大小、旋转等,最后把动画对象设置给视图的startAnimation方法。即先直接构造通用动画Animation,再把动画对象Animation传递给视图,由视图启动动画。

Animation类是抽象的视图动画类,它有如下几个子类:

  • AlphaAnimation:透明度改变的动画时要指定动画时要指定动画开始时的透明度、结束时的透明度和动画持续时间。其中透明度可从0变化到1。
  • ScaleAnimation:大小缩放的动画时要指定动画时要指定动画开始时的缩放比(以X、Y轴的缩放参数来表示)、结束时的缩放比(以X、Y轴的缩放参数来表示),并指定动画持续时间。由于缩放时以不同点为中心的缩放效果并不相同,日因此指定缩放动画时还要通过pivotX、pivotY来指定"缩放中心"的坐标。
  • TranslateAnimation:位移变化的动画时只要指定定动画开始时的位置(以X、Y坐标来表示)、结束时的位置(以X、Y坐标来表示),并打指定动画持续时间即可
  • RotateAnimation:旋转动画。创建该动画时只要指定动画开始时的旋转角度、结束时的旋转角度转角度,并指定动画持续时间即可。由于旋转时以不同点为中心的旋转效果并不相同,因此指定旋转动画时还要通过pivotX、pivotY来指定"旋转轴心"的坐标。

TranslateAnimation ‌只改变视图的绘制位置‌,‌需通过setFillAfte设置是否改变实际布局属性‌。当点击区域仍位于原始位置‌,即使视觉上已移动,可能导致交互错位。
‌Android 5.0+ 推荐使用 view.animate().translationX(...)‌(属性动画),更可靠且可支持硬件加速。

插值Interpolator

Interpolator控制在动画期间需要动态"补入"多少顿,具体在动画运行的哪些时刻补入帧,控制插入帧的行为。

Interpolator根据特定算法计算出整个动画所需要动态插入帧的密度和位置,最终实现动画帧的匀速、加速、减速、抛物线速度等各种速度变化。
Interpolator是一个接口,可以通过实现Interpolator来控制动画的变化速度。
Android为Interpolator提供了如下几个实现类,用于实现不同的动画变化速度。

  • LinearInterpolator:动画以均匀的速度改变。
  • AccelerateInterpolator:在动画开始的地方改变速度较慢,然后开始加速。
  • AccelerateDecelerateInterpolator:在动画开始、结束的地方改变速度较慢,在中间的时候加速。
  • CycleInterpolator:动画循环播放特定的次数,变化速度按正弦曲线改变。
  • DecelerateInterpolator:在动画开始的地方改变速度较快,然后开始减速。

在定义补间动画的<set.../>元素中设置android:interpolator属性,可指定为Android默认支持的Interpolator。例如:@android:anim/linear_interpolator,@android:anim/accelerate_interpolator。

定义动画资源之后,利用 AnimationUtils 工具类加载指定的动画资源,加载成功后返回 Animation对象, 动画视图使用该对象作为播放参数。

XML方式

res/anim目录下创建例如fade_in.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true">
<alpha
android:duration="2000"
android:fromAlpha="0.0"
android:interpolator="@android:anim/linear_interpolator"
android:toAlpha="1.0" />
</set>

然后在代码中加载这个动画,再应用到动画视图的播放方法中:

Animation fadeIn = AnimationUtils.loadAnimation(context, R.anim.fade_in);
view.startAnimation(fadeIn);

代码方式

直接在代码中创建动画,然后应用给动画视图的动画启动方法。

Animation fadeIn = new AlphaAnimation(0, 1);
fadeIn.setDuration(2000); // 设置动画持续时间
fadeIn.setFillAfter(true); // 保持动画结束时的状态
view.startAnimation(fadeIn);

更多示例:

<!--xml配置--> <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/accelerate_interpolator"> <!--从屏幕右侧飞入--> <translate android:fromXDelta="100%" android:toXDelta="0%" android:duration="200"/> <!--向屏幕右侧飞出--> <translate android:fromXDelta="0%" android:toXDelta="100%" android:duration="200"/> </set>
//代码加载 val translate: Animation? = AnimationUtils.loadAnimation(menuPanel.context, com.bjxdljg.common.R.anim.anim_in_from_right) menuPanel.startAnimation(translate)
//神图补间动画代码实现 //从屏幕右侧飞入 val translate: Animation= TranslateAnimation(Animation.RELATIVE_TO_SELF,1f, Animation.RELATIVE_TO_SELF,0f,Animation.RELATIVE_TO_SELF,0f,Animation.RELATIVE_TO_SELF,0f) translate.duration=200 menuPanel.startAnimation(translate) //向屏幕右侧飞出 val translate: Animation= TranslateAnimation(Animation.RELATIVE_TO_SELF,0f, Animation.RELATIVE_TO_SELF,1f,Animation.RELATIVE_TO_SELF,0f,Animation.RELATIVE_TO_SELF,0f) translate.duration=200 menuPanel.startAnimation(translate) //属性补间动画代码实现, //从屏幕右侧飞入 menuPanel.translationX=menuPanel.width.toFloat() menuPanel.animate().translationX(0f).setDuration(200).start()

自定义(视图)补间动画

Animation是视图补间动画抽象基类,系统为该抽象基类提供实现了AlphaAnimation、RotateAnimation、ScaleAnimation、Translate Animation四个视图补间动画的基本形式。在实际项目中可能还需要一些更复杂的动画,比如让图片在"三维"空间内进行旋转动画等,这需要继承Animation实现自定义补间动画。

为了控制视图进行三维空间的变换,需要借助于Android提供的android.graphics.Camera,这个Camera是一个空间变换工具,作用有点类似于Matrix,但功能更强大。

属性(补间)动画

属性动画是增强版的补间动画。属性动画直接作用于对象的属性上,它的直接作用只是在时间线上不断修改任何类型对象的任何属性值。

  • 视图补间动画只能定义两个关键帧在"透明度""旋转""缩放""位移"4个方面的变化,属性补间动画可以定义任何属性的变化。
  • 视图补间动画只能对UI组件执行动画,属性补间动画几乎可以对任何对象执行动画(不管它是否显示在屏幕上)。

Animator类是抽象的属性动画类,它有如下几个子类:

  • ValueAnimator:是Animator的子类,属性动画主要的时间引擎,它负责计算各个帧的属性值。它定义了属性动画的绝大部分核心功能,包括计算各帧的相关属性值,负责处理更新事件,按属性值的类型控制计算规则。属性动画主要由两方面组成:1计算各帧的相关属性值;2为指定对象设置这些计算后的值。ValueAnimator只负责第一方面内内容,因此程序员必须根据ValueAnimator计算并监听值更新来更新对象的相关属性值。
  • ObjectAnimator:是ValueAnimator的子类,允许对指定对象的属性执行动画。在实际应用中,ObjectAnimator使用起来更加简单,因此更加常用用。在少数场景下,由于ObjectAnimator存在一些限制,可能需要考虑使用ValueAnimator。
  • AnimatorSet:是Animator的子类,用于组合多个Animator,并指定多个Animator是按次序播放还是同时播放。

属性动画分为两类:ValueAnimator和ObjectAnimatorAnimatorSet用于组合多个动画。即先要由视图对象和其属性名称构造出动画对象Animator,然后由动画对象Animator启动动画。

ObjectAnimator继承了ValueAnimator,它可以直接将ObjectAnimator在动画过程中计算出来的值应用到指定对象的指定属性上,因此使用ObjectAnimator就不需要注册AnimatorUpdateListener监听器了。使用ObjectAnimator的ofint()、ofFloat()或ofObject(静态方法创建CObjectAnimator时,需要指
定具体的对象,以及对象的属性名。

与ValueAnimator不同的是,使用ObjectAnimator有如下几个注意点。

  • 要为该对象对应的属性提供setter方法。
  • 调用ObjectAnimator的ofint()、ofFloat()或 ofobject()工厂方法时,如果values...参数只提供了一个值(本来需要提供开始值和结束值),那么该值会被认为为是结束值。该对象应该为该属性提供一个getter方法,该getter方法的返回值将被作为开始值。
  • 如果动画的对象不是View,为了能显示动画效果,可能还需要在onAnimationUpdate()事件监听方法中调用View.invalidate()方法来刷新屏幕的显示,比如对]Drawable对象的color属性执行动画。但如果是View定义的setter方法,如setAlpha()和setTraInslationX()等方法都会自动地调用invalidate()方法,因此不需要额外地调用invalidat()方法。

Evaluator

属性动画还需要利用一个Evaluator(计算器)工具类,控制属性动画如何计算属性值。Android提供了如下Evaluator。

  • IntEvaluator:用于计算int类型属性值的计算器。
  • FloatEvaluator:用于计算float类型属性值的计算器。
  • ArgbEvaluator:用于计算以十六进制形式表示的颜色值的计算器。
  • TypeEvaluator:它是计算器接口,开发者可以通过实现该接口来实现自定义计算器。如果需要对int、float或者颜色值以外类型的属性执行属性动画,可能需要实现TypeEvaluator接口来实现自定义计算器。

Android8还为AnimatorSet新增了如下方法。

  • reverse():反向播放属性动画。通过reverse()方法则允许对动画进行倒播--以前可能需要定义两组动画,其中一组用于正向播放(比如放大、淡入);另一组用于反向播放(比如缩小、淡出),有了倒播功能之后,只需定义一组动画即可。
  • long getCurrentPlayTime():获取动画的当前播放时间。
  • setCurrentPlayTime(longplayTime):设置动画的播放时间。通过调用setCurrentPlayTime()方法,允许AnimatorSet动画直接调到指定时间点进行播放,不需要总是从头开始播放。

使用属性动画的步骤如下。

  1. 创建ValueAnimator或ObjectAnimator对象--既可从XML资源文件加载该动画资源,也可直接调用ValueAnimator或ObjectAnimator的静态工厂方法来创建动画。
  2. 为Animator对象设置属性。
  3. 如果需要监听Animator的动画开始事件、动画结束事件、动画重复事件、动画值改变事件,并根据事件提供相应的处理代码,则应该为Animattor对象设置事件监听器。
  4. 如果有多个动画需要按次序或同时播放,则应使用AnimatorSet组合这些动画。
  5. 调用Animator对象的start()方法启动动画。

ViewPropertyAnimator

android.view.ViewPropertyAnimator‌‌ 是 Android 提供的一个用于简化和优化对View对象属性进行动画处理的工具类。它并非继承自ValueAnimatorObjectAnimator,而是专门为View设计提供更简洁的链式调用语法,并在多属性同时动画时提升性能。

调用 view.animate().translationX()是使用 ‌ViewPropertyAnimator‌ 实现属性动画的一种常见方式,用于对 View 沿 X 轴进行平移动画。

使用SurfaceView实现动画

View的绘图机制存在如下缺陷:

  • View缺乏双缓冲机制。
  • 当需要更新View上的图片时,必须重绘View上显示的整张图片。
  • 新线程无法直接更新View组件。

Android提供了一个SurfaceView来代替View,在实现游戏绘图方面,SurfaceView比View性能高。

SurfaceView与普通View其中一个重要的区别:View的绘图小必须在当前U1线程中进行,而SurfaceView不会存在这个问题,因为SurfaceView的绘图是由SurfaceHolder来完成的。
对于View组件,如果程序需要花较长的时间来更新绘图,那么主UI线程将会被阻塞,无法响应用户的任何动作;而SurfaceHolder则会启用新的线程去更新SurfaceView的绘制,因此不会阻塞主UI线程。一般来说,如果程序界面的动画元素较多,而且很多动画元素的移动都需要通过定时器来控制,就可以考虑使用SurfaceView。

ViewFlipper

ViewFlipper可使用动画控制多个组件之间的切换效果。

1.ViewFlipper和OnGestureListener手势接口实现简单手势动画

要点如下:

ViewFlipper类继承自android.widget.ViewAnimator,它可以对内部的视图做动画,它支持2.0及以上。

在布局中添加ViewFlipper视图

<ViewFlipper android:id="@+id/ViewFlipper01" android:layout_width="fill_parent" android:layout_height="fill_parent">

</ViewFlipper>

在ViewFlipper中添加各个view:

flipper.addView(view1);

flipper.addView(view2);

实现OnGestureListener

构造GestureDetector detector = new GestureDetector(this);

重写activity的onTouchEvent方法:

public boolean onTouchEvent(MotionEvent event) {
return this.detector.onTouchEvent(event);
}

实现onFling方法:

public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
if (e1.getX() - e2.getX() > 120) {
this.flipper.setInAnimation(AnimationUtils.loadAnimation(this, R.anim.push_left_in));
this.flipper.setOutAnimation(AnimationUtils.loadAnimation(this, R.anim.push_left_out));
this.flipper.showNext();
return true;
} else if (e1.getX() - e2.getX() < -120) {
this.flipper.setInAnimation(AnimationUtils.loadAnimation(this, R.anim.push_right_in));
this.flipper.setOutAnimation(AnimationUtils.loadAnimation(this, R.anim.push_right_out));
this.flipper.showPrevious();
return true;
}
return false;
}

2.动画文件

在res\anim\*.xml中,例如:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="100%p" android:toXDelta="0" android:duration="500" />
<alpha android:fromAlpha="0.1" android:toAlpha="1.0" android:duration="500" />
</set>

这个动画中包含两个动作:

translation动画:fromXDelta 动画的开始X位置,toXDelta 动画的结束X位置,duration 持续时间。

alpha透明度通道动画:

layer-list

layer-list中的item有top,start、end、bottom属性,可以理解为内边距:top就是paddingTop,bottom就是paddingBottom。不推荐使用在Layer-List中直接动画。

不建议直接在layer-list中使用动画,因为layer-list主要用于组合静态图层。如果确实需要在第一层实现动画效果,可以将该层单独作为一个视图(例如ImageView),然后通过代码或XML属性动画来控制这个视图的动画。

对于位移动画,建议使用单独的视图(如ImageView)并通过属性动画来控制,而不是尝试在layer-list中直接实现。这样可以更灵活地控制动画效果,并且代码更加清晰、易于维护。如果确实需要在一个复杂的背景中结合多个动画效果,考虑将动画应用于单独的视图或使用矢量图和矢量动画。

AnimatorSet

在使用AnimatorSet时,‌推荐每次使用时都新建一个实例,而不是重用旧的AnimatorSet对象‌。

重用AnimatorSet可能会导致 ‌循环依赖异常‌(java.lang.IllegalStateException: circular dependencies cannot exist in animatorset),尤其是在动画执行过程中被多次启动或中断后。这是因为AnimatorSet内部会记录动画之间的依赖关系(如顺序、同时播放等),当同一个实例被重复使用时,这些依赖关系可能累积并形成循环引用,从而引发崩溃。

推荐做法

  1. 每次使用都新建‌:在需要启动动画时,创建一个新的AnimatorSet实例,并配置所需的动画。

  2. 避免重复调用start()‌:如果一个AnimatorSet已经在运行中,不要再次调用start(),这也会增加出现循环依赖的风险。

  3. 如需复用动画对象,复用的是ObjectAnimator‌:如果多个地方需要使用相同的动画效果(如缩放、移动),可以复用ObjectAnimator对象,但每次仍需将其添加到一个新的AnimatorSet中。

总结

  • 不要重用AnimatorSet实例。
  • 总是新建AnimatorSet实例来管理动画组合。
  • 可以安全地‌复用ObjectAnimatorValueAnimator等基础动画对象。

这种做法能有效避免循环依赖错误,确保动画稳定运行。‌

Scroller

Android里Scroller类 是为了实现View平滑滚动的一个Helper类。通常在自定义的View时使用,在View中定义一个私有成员mScroller = new Scroller(context)。设置mScroller滚动的位置时,并不会导致View的滚动,通常是用mScroller记录/计算View滚动的位置,再重写View的computeScroll(),完成实际的滚动。

http://www.jsqmd.com/news/1407948/

相关文章:

  • 2026 年现阶段宜宾资质齐全的库存涂料回收公司哪家强,这玩意儿居然能让积压的涂料变废为宝,看完你还舍得直接扔掉?-博源化工原料回收 - 行业推荐官【认证】
  • 盐城住户想找靠谱阳台管道疏通服务?实用挑选技巧赶紧收藏好 - 优企甄选
  • 2026 年更新:望都大型的抗爆墙同城获客企业哪个好,花小钱拿到精准客户的工厂,都偷偷用了这玩意儿-抖企盈讯呱呱获客服务 - 行业推荐官【认证】
  • 2026 年至今,浮山正规的不锈钢装饰井盖生产厂家哪家可靠,小区楼下装的这玩意儿,居然比普通井盖还多用10年? - 企业信息推荐-2
  • 无货源一件代发怎么设置地址?新手小白合规操作指南 - 抖掌柜一键下单
  • 2026年华东地区吹塑机性能测评 宁波金戈智能装备详解 - 起跑123
  • 2026年8月17日重庆市潼南区移动1000M宽带怎么办理 - 领卡园地
  • 智学果AI英语学习效果怎么样?真实体验者的观察 - 天下观知
  • 2026 年新消息:临猗可靠的液压升降平台租赁公司联系电话,租设备还能省出半个月工程款?揭秘工程人必知的高效工具方案-鼎力机械设备 - 行业推荐官-2
  • 2026 年当下,黔西南州靠谱的桥梁卸落支座源头厂家电话,这玩意儿竟能决定桥梁建成?看完彻底颠覆对市政工程的认知-长信橡胶 - 行业推荐官[官方】--
  • 2026年净化工程行业科普及惠州净化车间建设指南 - 起跑123
  • 2026年8月目前诗芬尼音响品牌推荐,诗芬尼汽车音响/诗芬尼音响改装/无损音响升级/汽车音响改装,诗芬尼音响定制厂家推荐 - 企业权威推荐大使
  • 肥东污水提升设备企业怎么选?看准这三点不踩坑 - 装修教育财税推荐2026
  • 石河子水下打捞服务|鱼塘潜水打捞手机施工团队哪家好-鸿腾水下打捞 - 行业推荐官【认证】
  • 2026优选:广西桂林国际电线电缆服务商怎么选?这份深度指南值得收藏 - 装修教育财税推荐2026
  • 微信网页版无法登录的终极解决方案:wechat-need-web 浏览器插件完整安装指南
  • 2026年高性价比液压阀块选购指南 济南乾照液压设备 - 起跑123
  • 镶黄旗优秀的直缝钢管加工费/3590钢护筒公司-鑫众森钢管 - 行业鉴选官
  • 2026 年衡南热门的长沙婚姻家庭律师怎么选供货商深度解析与优选指南,别再踩坑!这招帮你挑到靠谱的婚姻家庭律师,还能省一半冤枉钱? - 行业推荐官-2
  • 2026 年当下,交城口碑好的镀锌石笼网定制厂家联系方式,河堤挡岸的靠谱之选,这玩意儿居然比混凝土还耐用三十年?-庞泽丝网 - 行业鉴选官
  • 2026年辽宁陶瓷压力传感器模组主流厂家产品横向对比评测 - 起跑123
  • 2026年声学振动解析系统实测体验 使用效果全面解析 - 起跑123
  • 2026年东莞到印尼专线哪家好 高口碑服务商**一览 - 起跑123
  • 2026年8月口碑好的智能排程APS系统专业实施全指南 - 起跑123
  • 关于微型减速电机知名品牌有哪些,真正专业的销售会主动解释这三处技术差异 - 推客
  • 2026年宁波UV镀膜加工工厂横评 图煜科技核心优势解读 - 起跑123
  • 2026 年沧州口碑好的锌钢围栏加工厂哪家可靠,这种既能防坠又能防盗的户外围挡,为啥现在小区没人用了? - 行业推荐官[官方】--
  • 在职硕士备考怎么选?武汉口碑好的机构要看这几点 - 装修教育财税推荐2026
  • uni-router v2.1.0 升级:导航守卫全面支持返回值模式
  • 2026年8月知名的华新水泥供应商哪家专业,华新水泥哪家专业 - 企业权威推荐大使