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

android View详解—动画

旋转动画

一、使用 XML 方式(推荐)

1. 创建动画文件

在 res/anim 目录下新建一个 XML 文件,例如:rotate_animation.xml

?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"android:duration="1000"          <!-- 动画持续时间,毫秒 -->android:fromDegrees="0"          <!-- 起始角度 -->android:toDegrees="360"          <!-- 结束角度 -->android:pivotX="50%"             <!-- 旋转中心点 X 坐标 -->android:pivotY="50%"             <!-- 旋转中心点 Y 坐标 -->android:repeatCount="infinite"   <!-- 重复次数,infinite 表示无限循环 -->android:repeatMode="restart"     <!-- 重复模式,restart 表示每次都重新开始 -->
android:interpolator="@android:anim/linear_interpolator" /> <!-- 插值器 -->

2. 在代码中使用动画

mageView imageView = findViewById(R.id.imageView);
Animation rotateAnimation = AnimationUtils.loadAnimation(this, R.anim.rotate_animation);
imageView.startAnimation(rotateAnimation);

二、使用代码动态创建动画

ImageView imageView = findViewById(R.id.imageView);RotateAnimation rotateAnimation = new RotateAnimation(0f, 360f,                          // 起始角度,结束角度Animation.RELATIVE_TO_SELF, 0.5f,  // 旋转中心点 X 坐标Animation.RELATIVE_TO_SELF, 0.5f   // 旋转中心点 Y 坐标
);rotateAnimation.setDuration(1000);     // 动画持续时间
rotateAnimation.setRepeatCount(Animation.INFINITE); // 无限循环
rotateAnimation.setInterpolator(new LinearInterpolator()); // 线性插值器imageView.startAnimation(rotateAnimation);

三、使用属性动画(更灵活,推荐)

ImageView imageView = findViewById(R.id.imageView);ObjectAnimator rotateAnimator = ObjectAnimator.ofFloat(imageView, "rotation", 0f, 360f);
rotateAnimator.setDuration(1000);
rotateAnimator.setRepeatCount(ValueAnimator.INFINITE);
rotateAnimator.setInterpolator(new LinearInterpolator());
rotateAnimator.start();

四、暂停与恢复动画(属性动画)

// 暂停动画
rotateAnimator.pause();// 恢复动画
rotateAnimator.resume();

五、注意事项与建议:

性能优化:如果动画只是简单的旋转,推荐使用 XML 或属性动画。

重复次数:repeatCount 设置为 Animation.INFINITE 或 ValueAnimator.INFINITE 表示无限循环。

插值器选择

LinearInterpolator:匀速旋转

AccelerateInterpolator:加速旋转

DecelerateInterpolator:减速旋转

AccelerateDecelerateInterpolator:先加速后减速旋转

动画停止

使用 Animation 时调用 animation.cancel();
使用属性动画时调用 animator.cancel()。

平移动画

一、XML 视图动画(传统方式,最简单)

1. 创建动画文件

res/anim/translate_left_to_right.xml
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"android:duration="800"android:fromXDelta="-100%"android:toXDelta="0%"android:fromYDelta="0%"android:toYDelta="0%"
android:fillAfter="true" />   <!-- 动画结束后停在终点 -->
fromXDelta / toXDelta:水平方向位移,可用具体数值(dp、px)或百分比(相对自身或父容器)。
fromYDelta / toYDelta:垂直方向位移,同上。
fillAfter="true":动画结束后停留在最终位置(否则控件会闪回起点)

2. 使用动画

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

二、代码动态创建视图动画

TranslateAnimation anim = new TranslateAnimation(Animation.RELATIVE_TO_PARENT, -1.0f,   // fromXAnimation.RELATIVE_TO_PARENT,  0.0f,   // toXAnimation.RELATIVE_TO_PARENT,  0.0f,   // fromYAnimation.RELATIVE_TO_PARENT,  0.0f);  // toY
anim.setDuration(800);
anim.setFillAfter(true);
view.startAnimation(anim);

三、属性动画(ObjectAnimator,API 11+,最推荐)

优势:真正改变 View 的坐标,不会出现视图动画“点击区域还在原地”的问题;

兼容硬件加速,性能更好。

1. 水平位移

ObjectAnimator.ofFloat(view, "translationX", -view.getWidth(), 0f).setDuration(800).start();

2. 垂直位移

ObjectAnimator.ofFloat(view, "translationY", 0f, 200f).setDuration(800).start();

3. 组合位移(X+Y)

Path path = new Path();
path.moveTo(0f, 0f);
path.lineTo(200f, 100f);
ObjectAnimator.ofFloat(view, View.X, View.Y, path).setDuration(800).start();

四、常用扩展技巧

五、视图动画 vs 属性动画(避坑)

缩放动画

XML 视图动画

在 res/anim/scale_center.xml
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"android:duration="400"android:fromXScale="1.0"android:toXScale="1.5"android:fromYScale="1.0"android:toYScale="1.5"android:pivotX="50%"          <!-- 中心点:水平中点 -->android:pivotY="50%"          <!-- 中心点:垂直中点 -->
android:fillAfter="true" />   <!-- 动画结束后保持最终大小 -->

使用:

Animation anim = AnimationUtils.loadAnimation(context, R.anim.scale_center);
imageView.startAnimation(anim);

代码动态创建视图动画

ScaleAnimation anim = new ScaleAnimation(1f, 1.5f,      // 起始/结束 X 缩放1f, 1.5f,      // 起始/结束 Y 缩放Animation.RELATIVE_TO_SELF, 0.5f,  // 中心点 XAnimation.RELATIVE_TO_SELF, 0.5f); // 中心点 Y
anim.setDuration(400);
anim.setFillAfter(true);
imageView.startAnimation(anim);

属性动画(ObjectAnimator

真正改变 View 的 scaleX/scaleY,点击区域同步放大/缩小

imageView.setPivotX(imageView.getWidth()  / 2f);   // 中心点
imageView.setPivotY(imageView.getHeight() / 2f);ObjectAnimator scaleX = ObjectAnimator.ofFloat(imageView, "scaleX", 1f, 1.5f);
ObjectAnimator scaleY = ObjectAnimator.ofFloat(imageView, "scaleY", 1f, 1.5f);AnimatorSet set = new AnimatorSet();
set.playTogether(scaleX, scaleY);
set.setDuration(400);
set.start();

ViewPropertyAnimator(一行代码链式调用)

imageView.animate().scaleX(1.5f).scaleY(1.5f).setDuration(400).start();

常见需求速查表

注意点

视图动画(ScaleAnimation) 只改变绘制大小,点击区域不变

属性动画(ObjectAnimator / View.animate) 会真正改变 View 的大小和触控区域,推荐优先使用

若需兼容 API < 11,可引入 NineOldAndroids(已过时)或保留 XML 视图动画。

淡入淡出

XML 视图动画

在 res/anim/fade_in.xml(淡入)

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

res/anim/fade_out.xml(淡出)

<alpha xmlns:android="http://schemas.android.com/apk/res/android"android:duration="1000"android:fromAlpha="1.0"android:toAlpha="0.0"
android:fillAfter="true" />

使用:

Animation in  = AnimationUtils.loadAnimation(context, R.anim.fade_in);
Animation out = AnimationUtils.loadAnimation(context, R.anim.fade_out);view.startAnimation(in);   // 淡入
view.startAnimation(out);  // 淡出

代码动态创建视图动画

// 淡入

AlphaAnimation fadeIn = new AlphaAnimation(0f, 1f);
fadeIn.setDuration(1000);
fadeIn.setFillAfter(true);
view.startAnimation(fadeIn);

// 淡出

AlphaAnimation fadeOut = new AlphaAnimation(1f, 0f);
fadeOut.setDuration(1000);
fadeOut.setFillAfter(true);
view.startAnimation(fadeOut);

属性动画(ObjectAnimator,推荐)

// 淡入

ObjectAnimator.ofFloat(view, View.ALPHA, 0f, 1f).setDuration(1000).start();

// 淡出

ObjectAnimator.ofFloat(view, View.ALPHA, 1f, 0f).setDuration(1000).start();

ViewPropertyAnimator(一行链式)

view.animate().alpha(1f)   // 淡入.setDuration(1000).start();view.animate().alpha(0f)   // 淡出.setDuration(1000)
.start();

交叉淡入淡出(两个 View 场景切换)

View oldView = findViewById(R.id.old);
View newView = findViewById(R.id.new);// 先把新 View 设为透明
newView.setAlpha(0f);
newView.setVisibility(View.VISIBLE);oldView.animate().alpha(0f).setDuration(500).withEndAction(() -> {oldView.setVisibility(View.GONE);newView.animate().alpha(1f).setDuration(500).start();}).start();

常见需求速查表

视图动画(AlphaAnimation) 只改变绘制透明度,不触发 setVisibility() 事件;如需隐藏,记得手动 setVisibility(GONE)。

属性动画(ObjectAnimator / View.animate) 会真正修改 View.ALPHA,可配合 setVisibility() 实现更复杂的场景切换。

交叉淡入淡出时,两个 View 必须位于同一个父布局,且新 View 初始 visibility = VISIBLE + alpha = 0。

动画插值器

LinearInterpolator  匀速 旋转加载圈

AccelerateInterpolator 越来越快 页面滑出

DecelerateInterpolator 越来越慢 页面滑入

AccelerateDecelerateInterpolator 两头慢中间快 默认效果

AnticipateInterpolator 先回拉再前进 弹出菜单

OvershootInterpolator 冲过头再回弹 点赞放大

AnticipateOvershootInterpolator 回拉 + 冲过头 卡片翻转

BounceInterpolator 落地弹跳 掉落按钮

CycleInterpolator(float cycles) 正弦循环 抖动提示

FastOutSlowInInterpolator Material 默认 所有 Material 动效

LinearOutSlowInInterpolator 先快后慢 Snackbar 滑出

FastOutLinearInInterpolator 先慢后快 返回按钮

设置插值器

setInterpolator

 android:interpolator="@android:anim/accelerate_decelerate_interpolator"

AnimationListener视图动画

AnimationListener 是 视图动画(View Animation) 专用的回调接口,用来监听 Animation 的生命周期事件
当使用 AlphaAnimation、ScaleAnimation、TranslateAnimation、RotateAnimation、AnimationSet 等旧版补间动画时,通过它可以在动画开始、结束、重复时执行额外逻辑。

Animation anim = AnimationUtils.loadAnimation(context, R.anim.fade_in);anim.setAnimationListener(new Animation.AnimationListener() {@Overridepublic void onAnimationStart(Animation animation) {Log.d("TAG", "动画开始");}@Overridepublic void onAnimationEnd(Animation animation) {Log.d("TAG", "动画结束");view.setVisibility(View.GONE); // 常见操作}@Overridepublic void onAnimationRepeat(Animation animation) {Log.d("TAG", "动画重复");}
});view.startAnimation(anim);

AnimatorListener属性动画

Android 属性动画(ObjectAnimator、ValueAnimator、AnimatorSet 等)的监听器接口叫 AnimatorListener,位于
包 android.animation.Animator.AnimatorListener。它与“视图动画”的 AnimationListener 不同,后者只适用于旧版补间动画。

  1. 接口方法一览

AnimatorUpdateListener属性动画

Android 属性动画体系里,AnimatorUpdateListener 是 ValueAnimator(包括其子类 ObjectAnimator、AnimatorSet)提供的“帧级”回调接口。
它会在每一帧刷新时调用一次,让你拿到「当前这一帧算出来的值」并手动刷新 UI,是自定义动画的核心手段。

ValueAnimator valueAnim = ValueAnimator.ofFloat(0f, 100f);  // 值区间
valueAnim.setDuration(1000);valueAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {// 1. 取出当前帧值float curValue = (float) animation.getAnimatedValue();// 2. 手动赋给任意属性textView.setTranslationX(curValue);// 3. 如需要,可刷新自定义 View// invalidate();}
});valueAnim.start();

Android 动画类型

一、视图动画(View Animation,API 1+)

子类:Tween Animation(补间动画)和 Frame Animation(逐帧动画)。

特点:只改绘制矩阵,不改真实属性;点击区域不跟随;兼容所有版本。

典型使用:AlphaAnimation、ScaleAnimation、TranslateAnimation、RotateAnimation、AnimationDrawable。

二、属性动画(Property Animation,API 11+)

核心类:ValueAnimator、ObjectAnimator、AnimatorSet。

特点:真正改变对象属性值;支持可暂停、可逆、可插值;点击区域同步。

兼容低版本:NineOldAndroids(已弃用),或使用 AndroidX Core 的 ViewCompat.animate()。

三、转场动画(Transition Framework,API 19+)

包路径:android.transition.*

适用场景:Activity/Fragment 切换、布局内容变化(如列表→详情)。

核心 API:

·  Explode、Slide、Fade

·  TransitionManager.beginDelayedTransition()

共享元素:ActivityOptions.makeSceneTransitionAnimation()

特点:自动捕捉起始/结束状态并执行补间;与属性动画底层打通。

四、矢量动画(Animated Vector Drawable / Vector Animation,API 21+)

文件格式:res/drawable/animated_vector.xml

使用:

静态矢量图 vector

动画指令 objectAnimator 嵌入到 <target> 节点

场景:图标动效、加载动画、路径变形(path morphing)

兼容:使用 AnimatedVectorDrawableCompat(API 14+)

五、物理动画(Physics-based Animation,API 16+)

框架 androidx.dynamicanimation:dynamicanimation

子类: 

SpringAnimation(弹簧)

FlingAnimation(甩动/惯性滑动)

特点:基于物理模型(阻尼、刚度、摩擦),真实自然;无需指定时长和终止值。


文章转载自:

http://xaeOD8Re.nfbkz.cn
http://0JFE9aDa.nfbkz.cn
http://GqDw2dxv.nfbkz.cn
http://od6r5TsW.nfbkz.cn
http://jSnhfv9W.nfbkz.cn
http://mlyqNUtw.nfbkz.cn
http://pdMyqC23.nfbkz.cn
http://v7MXAmMO.nfbkz.cn
http://irVEFeSk.nfbkz.cn
http://0VCjvYvC.nfbkz.cn
http://t7BIWv9Q.nfbkz.cn
http://4T88IQmJ.nfbkz.cn
http://W33AHy4E.nfbkz.cn
http://ry5JEjKd.nfbkz.cn
http://fAshoPSF.nfbkz.cn
http://rFaah7kw.nfbkz.cn
http://uqns7EDb.nfbkz.cn
http://b7V2bkpi.nfbkz.cn
http://xInq0rRm.nfbkz.cn
http://TyxofNCJ.nfbkz.cn
http://WMXzJaAt.nfbkz.cn
http://G25vQyCj.nfbkz.cn
http://FdV9CAw2.nfbkz.cn
http://sQ5Y3HLi.nfbkz.cn
http://XnXMlW8G.nfbkz.cn
http://9kDJU7T8.nfbkz.cn
http://thZtLRcV.nfbkz.cn
http://kNpMKJGZ.nfbkz.cn
http://6WdS0dUr.nfbkz.cn
http://F4pCc3Zj.nfbkz.cn
http://www.dtcms.com/a/368684.html

相关文章:

  • 2024年9月GESPC++三级真题解析(含视频)
  • ASP.NET Core文件分片上传
  • OCA、OCP、OCM傻傻分不清?Oracle认证就看这篇
  • 面试了一个外包公司,面试不到5分钟就出来,这问题问得有点变态。。。。。。
  • Matlab使用小技巧合集(系列四):Table类型高效用法与数据处理实战
  • 25高教社杯数模国赛【C题超高质量思路+可运行代码】第十弹
  • WinForms 项目里生成时选择“首选目标平台 32 位导致有些电脑在获取office word对象时获取不到
  • ANSYS 热力耦合计算
  • UE4 Mac构建编译报错 no member named “disjunction” in namespace “std”
  • 深度相机详解
  • vue 经常写的echarts图表模块结构抽取
  • 蚂蚁 S21e XP Hyd 3U 860T矿机性能分析与技术特点
  • Python迭代协议完全指南:从基础到高并发系统实现
  • CT影像寻找皮肤轮廓预处理
  • 7种流行Prompt设计模式详解:适用场景与最佳实践
  • uni-app 项目 iOS 上架踩坑经验总结 从证书到审核的避坑指南
  • 3.3_第一行之hard_local_irq_disable
  • 汽车 信息娱乐系统 概览
  • 将已有 Vue 项目通过 Electron 打包为桌面客户端的完整步骤
  • Nginx 配置片段主要用于实现​​正向代理​​,可以用来转发 HTTP 和 HTTPS 请求
  • 有鹿机器人的365天奇幻日记:我在景区当扫地僧
  • C++算法专题学习——分治
  • 智能工单路由系统(Java)
  • 生成模型实战 | 深度分层变分自编码器(Nouveau VAE,NVAE)
  • Windows多开文件夹太乱?Q-Dir四窗口同屏,拖拽文件快一倍
  • 测试驱动开发 (TDD) 与 Claude Code 的协作实践详解
  • Bug 排查日记:打造高效问题定位与解决的技术秘籍
  • MySQL InnoDB索引机制
  • Nextcloud 实战:打造属于你的私有云与在线协作平台
  • linux上nexus安装教程