Android 动画初探

简介: 前言:好久没来写文章了,一方面是因为自己懒了,另外一个是因为最近工作比较忙,没有闲时间(其实主要还是因为懒)。话说八月多换了一个新工作,在之前的公司,主要是横向发展,了解了很多技术。

前言:

好久没来写文章了,一方面是因为自己懒了,另外一个是因为最近工作比较忙,没有闲时间(其实主要还是因为懒)。话说八月多换了一个新工作,在之前的公司,主要是横向发展,了解了很多技术。在现在的公司主要是纵向发展,更加深入的探索。之前是广而不精,没有深入学习。在现在的公司呢,能够更加深入的学习技术。就拿最近的工作来说吧,动画很多,刚开始只是知道Android动画分为属性动画、帧动画和补间动画。但是,他们之间有什么具体的区别就不是特别清楚了。尤其是属性动画和补间动画的区别,我能说自己被补间动画坑惨了吗?(其实,还是自己学艺不精,需要继续努力了。)好了,废话说多了,还是来看看今天的文章吧。

首先

要学习Android动画,我们以一个例子来深入学习,毕竟都是要把功能实现出来,写一些大而空没有实用性的东西,不但是敷衍别人,更是对自己的不负责任。如下图所示:(原谅我自恋一下,放了自己的图像照)


img_007076d08e227ccd04cedf7a33fbc322.png
Screenshot_20181023-200259.png
img_b1fea48c6be93cda025c06fecde17f4d.png
Screenshot_20181023-200103.png
  • 分析
    1、要实现从大图到小图的过度,我们需要怎么实现呢?又需要用哪些技术呢?首先图片缩小了,那么就需要缩放动画;其次,图片向右移动和向上移动了,那么就需要位移动画。背景动画是用Lottie实现的,中间的圆形变叉也是用的lottie监听帧率变化,这个不在今天的讨论和实现范围内。今天主要实现布局从大到小的缩放和移动。
    2、 那么缩放和移动可以用哪些动画实现呢?可能有朋友说是用补间动画实现了,那么如果布局上面有点击事件呢?点击事件的位置在原位置还是新位置呢?答案是还在原来的位置,补间动画只能实现view的变化,而不能改变点击事件的位置,如果只是做一个页面展示用,那么补间动画完全够用了。但是,如果想改变点击事件的位置,必须要用属性动画。我能说我在这里被坑了好久吗?好了,现在来看看我们如何实现控件的缩放和移动。

其次

 /**
   * 动画
   */
public static void scanAnimation(Context context, FrameLayout mLytAll) {
    WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    DisplayMetrics dm = new DisplayMetrics();
    wm.getDefaultDisplay().getMetrics(dm);
    final int width = dm.widthPixels;// 屏幕宽度(像素)
    int height = dm.heightPixels;// 屏幕高度(像素)
    ObjectAnimator translationX = ObjectAnimator.ofFloat(mLytAll,
            "translationX", 1,
            (DensityUtils.px2dp(context, width) - 36));
    ObjectAnimator translationY = ObjectAnimator.ofFloat(mLytAll,
            "translationY", 1,
            -(DensityUtils.px2dp(context, height) - 23));


    ObjectAnimator scaleX = ObjectAnimator.ofFloat(mLytAll,
            "scaleX", (94 / DensityUtils.px2dp(context, width)));
    ObjectAnimator scaleY = ObjectAnimator.ofFloat(mLytAll,
            "scaleY", (166 / DensityUtils.px2dp(context, height)));

    AnimatorSet animatorSet = new AnimatorSet();  //组合动画
    animatorSet.playTogether(translationX, translationY, scaleX, scaleY); //设置动画
    animatorSet.setDuration(350);
    animatorSet.start();
}
  • 分析:
    1、这里要移动,那么就需要屏幕的宽和高,然后进行等比缩放,因为上面和右边有一定的距离,那么就要计算右边距和上边距;
    2、这里因为是X轴和Y轴进行移动并且缩放,所以我这边用了组合动画,AnimatorSet;
    3、X轴的移动动画用了ObjectAnimator然后设置X轴移动和Y轴移动,。假设,距离右边距是36dp,上边距是23。那么X轴的移动就是,从1到屏幕宽转换成dp值后减去右边距(36dp)。Y轴的移动就是屏幕的高转换为dp后减去上边距(23dp),然后加上一个负号(-),为什么呢,因为Y轴向上为负,向下为正;
    4、现在来看缩放动画,假设缩放后的小屏幕高是166dp,宽是94dp,那么就是缩放后的屏幕宽(94dp)除以屏幕宽转换成dp值之后的比率了。当然,这样做显然是不太严谨的(为什么说不严谨呢,后面会讲)。Y轴的缩放呢就是缩放后小图的高(166dp)除以屏幕高转换成dp之后的值。
    5、完成后用AnimatorSet设置X轴Y轴的平移和缩放动画同步进行,然后设置动画的执行时长至此就完成了动画从大屏幕到小屏幕的移动和缩放。

再次

之前在分析的时候说上面直接写死宽高值之后进行缩放不严谨,那么我们来分析一下。因为Android手机屏幕分辨率很多,如果在大屏幕手机上面可能不会出现太大的问题,那么在屏幕分辨率比较低的手机上呢?有可能显示不全或者按钮挤压到一起去了。那么,就要动态计算小屏幕的宽高了。比如说UI给了我们的UI图的宽高比是360640,那么我们如何来动态计算屏幕的宽高比呢?那么,X轴的缩放比率就不应该是94/DensityUtils.px2dp(context, width))了,而应该是(94(DensityUtils.px2dp(context, width))/360))/DensityUtils.px2dp(context, width)),就是说我们应该计算UI图的宽和手机实际的宽的比率乘以94再除以屏幕的宽,这才是我们需要缩放的宽。那么高呢?当然是一样的了166 / DensityUtils.px2dp(context, height)),这样写当然也是有问题的了,而应该是(166*(DensityUtils.px2dp(context, height))/640))/DensityUtils.px2dp(context, height)),这样才是更加严谨的写法。

/**
 * 动画
 */
public static void scanAnimation(Context context, FrameLayout mLytAll) {
   WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
   DisplayMetrics dm = new DisplayMetrics();
   wm.getDefaultDisplay().getMetrics(dm);
   final int width = dm.widthPixels;// 屏幕宽度(像素)
   int height = dm.heightPixels;// 屏幕高度(像素)
   ObjectAnimator translationX = ObjectAnimator.ofFloat(mLytAll,
        "translationX", 1,
        (DensityUtils.px2dp(context, width) - 36));
  ObjectAnimator translationY = ObjectAnimator.ofFloat(mLytAll,
        "translationY", 1,
        -(DensityUtils.px2dp(context, height) - 23));


   ObjectAnimator scaleX = ObjectAnimator.ofFloat(mLytAll,
        "scaleX", ((94(DensityUtils.px2dp(context, width)/360)) / DensityUtils.px2dp(context, width)));
   ObjectAnimator scaleY = ObjectAnimator.ofFloat(mLytAll,
        "scaleY", ((166(DensityUtils.px2dp(context, height)/640)) / DensityUtils.px2dp(context, height)));

   AnimatorSet animatorSet = new AnimatorSet();  //组合动画
   animatorSet.playTogether(translationX, translationY, scaleX, scaleY); //设置动画
   animatorSet.setDuration(350);
   animatorSet.start();
}

最后

好了,今天就写到这里,如果有不正确的还希望各位指正,小可这里不胜感激,还有就是,能用属性动画实现的,尽量不要用补间动画来做,因为你会碰到各种坑。

相关文章
|
4月前
|
存储 Shell Android开发
基于Android P,自定义Android开机动画的方法
本文详细介绍了基于Android P系统自定义开机动画的步骤,包括动画文件结构、脚本编写、ZIP打包方法以及如何将自定义动画集成到AOSP源码中。
84 2
基于Android P,自定义Android开机动画的方法
|
2月前
|
Android开发 UED
Android 中加载 Gif 动画
【10月更文挑战第20天】加载 Gif 动画是 Android 开发中的一项重要技能。通过使用第三方库或自定义实现,可以方便地在应用中展示生动的 Gif 动画。在实际应用中,需要根据具体情况进行合理选择和优化,以确保用户体验和性能的平衡。可以通过不断的实践和探索,进一步掌握在 Android 中加载 Gif 动画的技巧和方法,为开发高质量的 Android 应用提供支持。
|
7月前
|
Java Android开发 开发者
Android10 修改开发者选项中动画缩放默认值
Android10 修改开发者选项中动画缩放默认值
208 0
|
7月前
|
XML Java Android开发
android的三种动画
android的三种动画
39 0
|
5月前
|
XML Android开发 数据格式
Android 中如何设置activity的启动动画,让它像dialog一样从底部往上出来
在 Android 中实现 Activity 的对话框式过渡动画:从底部滑入与从顶部滑出。需定义两个 XML 动画文件 `activity_slide_in.xml` 和 `activity_slide_out.xml`,分别控制 Activity 的进入与退出动画。使用 `overridePendingTransition` 方法在启动 (`startActivity`) 或结束 (`finish`) Activity 时应用这些动画。为了使前 Activity 保持静止,可定义 `no_animation.xml` 并在启动新 Activity 时仅设置新 Activity 的进入动画。
140 12
|
6月前
|
Android开发 UED
Android Item平移动画
【6月更文挑战第18天】
114 8
|
5月前
|
XML Android开发 UED
Android动画之共享元素动画简单实践
本文介绍Android共享元素动画, 实现两Activity间平滑过渡特定UI元素。通过设置`transitionName`属性和使用`ActivityOptions.makeSceneTransitionAnimation`启动目标Activity实现动画效果。可自定义过渡动画提升体验。
78 0
|
5月前
|
Android开发
android 动画 插值器和估值器
android 动画 插值器和估值器
|
7月前
|
数据库 Android开发
Android数据库框架-GreenDao入门,2024年最新flutter 页面跳转动画
Android数据库框架-GreenDao入门,2024年最新flutter 页面跳转动画
Android数据库框架-GreenDao入门,2024年最新flutter 页面跳转动画