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();
}

最后

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

优秀的个人博客,低调大师

微信关注我们

原文链接:https://yq.aliyun.com/articles/665079

转载内容版权归作者及来源网站所有!

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

相关文章

发表评论

资源下载

更多资源
Mario,低调大师唯一一个Java游戏作品

Mario,低调大师唯一一个Java游戏作品

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Oracle Database,又名Oracle RDBMS

Oracle Database,又名Oracle RDBMS

Oracle Database,又名Oracle RDBMS,或简称Oracle。是甲骨文公司的一款关系数据库管理系统。它是在数据库领域一直处于领先地位的产品。可以说Oracle数据库系统是目前世界上流行的关系数据库管理系统,系统可移植性好、使用方便、功能强,适用于各类大、中、小、微机环境。它是一种高效率、可靠性好的、适应高吞吐量的数据库方案。

Apache Tomcat7、8、9(Java Web服务器)

Apache Tomcat7、8、9(Java Web服务器)

Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache、Sun 和其他一些公司及个人共同开发而成。因为Tomcat 技术先进、性能稳定,而且免费,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web 应用服务器。

Sublime Text 一个代码编辑器

Sublime Text 一个代码编辑器

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。