热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

Android动画实现原理和代码

这篇文章主要介绍了Android动画实现原理和代码分析,如果你对此感兴趣,跟着小编学习下吧。

我们都知道,漂亮的用户界面是衡量一款应用”好坏”很重要的依据,因为人都是视觉动物,就好比说花容月貌总有男人为之倾倒,英俊潇洒总能博得芳心。这是一个不容置疑的事实,那么我们的应用也是如此,一个漂亮的用户交互界面能提升用户对应用的好感,提升用户体验。而动画是提升用户体验的一个重要因素,好的动画交互让人用着更舒心,那么今天的这篇文章就是介绍Android中动画实现,让我们的应用动起来。

Android动画分类

在Android中我们一般将动画分为两类,一类是View Animation(视图动画),一类是Property Animation,当然也有说分为三种,Frame Animation,Tween Animation,和Property Animation,由于前两种一般都是作用于整个View的,所以就统称为View Animation。在谷歌官方文档中也是按两种分类来讲解的。

在Android 5.0开始增加了Material Design ,Material Design 中实现了一些动画为用户提供操作反馈并在用户与您的应用进行互动时提供视觉连续性。 它将为按钮与操作行为转换提供一些默认动画,我们可以定制触摸反馈,使用揭露效果,定制操作行为转换,指定定制转换,使用转换启动一个操作行为,以共享元素启动一个操作行为等等。

Frame Animation

由于Frame Animation,Tween Animation的实现还是有区别的,暂且就将这两种方式实现分开介绍,Frame Animation其实就是将一系列的图片一张一张的展示出来,这个和我们看电影是类似的,由于人眼有一个可接收的暂留时间,这也就是为什么人在线看视频会感觉卡顿。当然我们实现Frame Animation就是这个依据,当播放相同的图片张数用时越短也就越流畅,自然人就会感觉是一个动画。我们常见的Gif其实也是帧动画,如果你用PhotoShop打开Gif动画,会发现里面是有很多图层的也就是很多帧。

对于Frame动画有两种实现方式,第一种方式就是在drawable文件夹下创建一个xml文件。它的语法很简单,如下

<&#63;xml version="1.0" encoding="utf-8"&#63;>

  

 

看了上面你会发现实现Frame动画很简单,属性很少,animation-list 是动画的根元素,在根元素中的oneshot属性表示动画执行次数,如果设置为true表示只播放一次,如果false则表示会一直循环执行。在根元素下有item元素,该元素就是我们要添加的图片,每一个item表示一帧,item下的drawable就是我们的图片资源,duration就是该帧动画执行的时间。例如

<&#63;xml version="1.0" encoding="utf-8"&#63;>

  
  
  
  
  
  
  
  

使用方法如下

//可以在xml中设置background  
   imageView.setBackgroundResource(R.drawable.frame_run_animation);
AnimationDrawable animatiOnDrawable= (AnimationDrawable) imageView.getBackground();
animationDrawable.start();

frame.gif

运行效果图如上,在上面我们没有添加oneshot属性,则该属性默认false,也就是说该动画会一直循环执行,当我们设置true后则播放到最后一帧时动画停止,当我们想停止时可以使用AnimationDrawable 的stop方法,它还提供了isRunning()方法判断是否已经在执行动画。另外我们还需要注意的是小心OOM。

当然用代码实现也很简单,如下

private void addFrame() {
    AnimationDrawable animatiOnDrawable= new AnimationDrawable();
    int[] mipmaps = new int[]{R.mipmap.run1, R.mipmap.run2, R.mipmap.run3,
        R.mipmap.run4, R.mipmap.run5, R.mipmap.run6, R.mipmap.run7, R.mipmap.run8,};
    for (int i = 1; i <= 8; i++) {
      int id=mipmaps[i-1];
      //或者使用下面方式,注意如果图片资源放在drawable下时将mipmap修改下
      //int id = getResources().getIdentifier("run" + i, "mipmap", getPackageName());
      Drawable drawable = getResources().getDrawable(id);
      animationDrawable.addFrame(drawable, 200);
    }
    animationDrawable.setOneShot(false);
    imageView.setBackgroundDrawable(animationDrawable);
    animationDrawable.start();
  }

Tween Animation

Tween Animation即补间动画,主要分为四种,分别是平移、缩放、旋转、透明度,直接上语法

<&#63;xml version="1.0" encoding="utf-8"&#63;>

  
  
  
  
  
    ...
  

这是官方给的语法,set 是一个动画集合,内部可以是多个动画的组合,也可以嵌套set,这里包含了动画实现的所有属性。在上面的语法中我们需要注意的是平移的时候其实位置接受百分比数值:从-100到100的值,以“%”结尾,表示百分比相对于自身;从-100到100的值,以“%p”结尾,表示百分比相对于父容器。例如平移开始位置在自身中间则是50%,如平时开始位置在父容器的则是50%p.

例如有些人给我们的Activity会加一些从左边进右边出的动画,那么当我们打开Activity时将Activity布局的fromXDelta值-100%p并将toXDelta为0%p,那么我们看到的效果就是从左边进入了。

插值器

在动画插值器起的作用主要是改变动画的执行速率,一般情况我们不需要自己实现插值器,因为在Android中已经给我们提供了9种插值器,应该够我们使用了,我们使用插值器后会让动画执行的效果更酷炫,当然想自定义插值器也不难,可以查看已经实现插值器源码做参考。

accelerate_decelerate_interpolator:先加速后减速accelerate_interpolator:一直加速anticipate_interpolator: 开始的时候先向后甩一点然后向前,就好比人扔东西会先向后甩一下,这样才能抛的远anticipate_overshoot_interpolator:和上一种插值器相似,先向后抛然后向前,到达终点后会有回弹一下效果,好比我们将球抛到墙上,然后反弹回来bounce_interpolator:动画结束的时候弹起,类似皮球落地,会弹几下才停止cycle_interpolator:动画循环播放特定的次数回到原点,速率改变沿着正弦曲线decelerate_interpolator:减速的插值器,刚开始速度快,然后越来越慢直到停止linear_interpolator:线性的插值器。从开始到结束匀速运动overshoot_interpolator:向前超过设定值一点然后返回

下面简单实现一个动画,动画效果如下面截图,是一个透明度,平移,缩放的动画同时执行的动画。

frame1.gif

<&#63;xml version="1.0" encoding="utf-8"&#63;>

  
  
  

 

然后使用下面代码给ImageView加入动画。

Animation animation= AnimationUtils.loadAnimation(this,R.anim.anim_in_left_top);
 imageView.startAnimation(animation);

 

当然我们也可给动画加上监听。如

animation.setAnimationListener(new Animation.AnimationListener() {
          @Override
          public void onAnimationStart(Animation animation) {
          }
          @Override
          public void onAnimationEnd(Animation animation) {
          }
          @Override
          public void onAnimationRepeat(Animation animation) {
          }
        });

上面的监听分别是动画开始结束和更新时候的回调。我们在回调中做一些额外的操作。在代码中实现动画就不在细说,主要对应AnimationSet, TranslateAnimation,ScaleAnimation,AlphaAnimation,RotateAnimation。

Propterty Animation

属性动画是3.0之后引入的,在View动画中虽然我们看到了我们的控件位置发生发生变化,比如Button虽然位置变化了,但是点击响应区域还在原来的位置。而属性动画就可以解决这种问题。它可以作用于View的属性。
语法


  
  

  
    ...
  

下面列出了常见的属性名字,另外需要注意的是,使用属性动画时,必须有相应属性的set/get方法,否则属性动画没有效果的。

translationX 和 translationY : 控制View距离左边和顶部的距离的增加值。是一个相对值。相对于自身位置的具体。

rotation 、 rotationX 和 rotationY : rotation 是控制View围绕其支点进行旋转。 rotationX 和 rotationY 分别是围绕X轴和Y轴旋转。

scaleX 和 scaleY : 控制View的缩放。

pivotX 和 pivotY : 控制View的支点位置,进行旋转和缩放,默认是View的中点。它们都是 float 值, 0 表示View的最左边和最顶端, 1 表示最右端和最下端。

alpha : 控制View的透明度。

x 和 y : 控制View在布局容器中距离左边和顶部的距离。是一个绝对值。

例如我们实现一个旋转加透明度变化的动画,效果图如下

frame1.gif

<&#63;xml version="1.0" encoding="utf-8"&#63;>

  
  

然后

AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(this,
        R.animator.property_animator);
set.setTarget(imageView);
set.start();

 

当然不用xml书写也是很简单的,如下代码

ObjectAnimator.ofFloat(imageView,"rotation",0,180,90,180)
.setDuration(2000).start();

代码实现的效果就是在2秒内先旋转到180度,在回到90度在转回180度
效果图如

frame1.gif

在上面代码实现了一直属性动画,那么如果我们想同时作用几个属性那该如何操作呢。此时我们有两种实现方式分别是类PropertyValuesHolder和AnimatorSet,话不多说,先上图再直接上代码。

frame1.gif

private void startPropertyAnimation3(){
    PropertyValuesHolder translatiOnX= PropertyValuesHolder.ofFloat("translationX", -200,-100,100, 200,300);
    PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 1.0f, 2.0f);
    PropertyValuesHolder rotate = PropertyValuesHolder.ofFloat("rotation", 0f, 360f);
    PropertyValuesHolder rotatiOnY= PropertyValuesHolder.ofFloat("rotationX", 0f, 180f);
    ObjectAnimator together = ObjectAnimator.ofPropertyValuesHolder(imageView, translationX,rotate, scaleX, rotationY);
    together.setDuration(3000);
    together.start();
  }
//或者使用AnimatorSet,此方法使用的是按顺序播放。
  private void startPropertyAnimation4(){
    ObjectAnimator translatiOnX= ObjectAnimator.ofFloat(imageView, "translationX", -200,-100,100, 200,300);
    ObjectAnimator scaleX = ObjectAnimator.ofFloat(imageView, "scaleX", 1.0f, 2.0f).setDuration(1000);
    ObjectAnimator rotation = ObjectAnimator.ofFloat(imageView, "rotation", 0f, 360f).setDuration(1000);
    ObjectAnimator rotatiOnX=ObjectAnimator.ofFloat(imageView,"rotationX", 0f, 180f).setDuration(1000);
    AnimatorSet set = new AnimatorSet();
    set.playSequentially(translationX, scaleX, rotation,rotationX);
    set.setDuration(4000);
    set.start();
  }

Fragment/Activity动画

其实实现Activity及Fragment切换动画也是很简单的,具体的动画效果制作可以使用即使上面介绍的补间动画。例如我们Fragment动画。

FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_right);
transaction.replace(R.id.fragment_container, fragment, fragmentTag);
transaction.commit();

Activity实现动画也很简单,在Activity中提供了overridePendingTransition(int enterAnim, int exitAnim) 方法,该方法接收两个参数,第一个参数是Activity进入时的动画,第二个参数是Activity退出时的动画。该方法一般写在startActivity()后和finish()后,如果我们想打开或者退出不显示动画,可将参数设置为0。

在上面的我们介绍了Activity/Fragment在代码中实现动画的方法,当然还有一种简单的实现方式,那就是在主题中设置动画。
对于Activity


  

可能你不太理解为什么是设置了四种,假如有Activity1和Activity2。当我们在Activity1中跳转到Activity2时,Activity1在页面上消失是执行的:activityOpenExitAnimation动画,Activity2出现在屏幕上执行的动画是activityOpenEnterAnimation。当Activity2 finish返回Activity1时,Activity2执行的动画是activityCloseExitAnimation,Activity1显示在屏幕执行的是activityCloseEnterAnimation。创建上面主题后我们需要将该主题应用到我们的Activty中就可以了。

同理Fragment也可相应设置,如activityCloseEnterAnimation改为fragmentCloseEnterAnimation即可。

除此之外我们也可以使用windowAnimation,它包括 windowEnterAnimation 和 windowExitAnimation。注意的一点就是WindowAnimation的控制权大于Activity/Fragment Animation的控制权。

除了上面介绍的动画实现,还有一些动画是从Android5.0增加的,你可以参考文末给出的链接文章,酷炫的Activity切换动画,打造更好的用户体验。个人感觉这篇文章介绍的挺详细。对本文缺少的内容也做了一个补充。到这里该篇文章就暂时告一段落,有问题欢迎指出,Have a wonderful day.

定义定制动画

酷炫的Activity切换动画,打造更好的用户体验


推荐阅读
  • 本文介绍了使用kotlin实现动画效果的方法,包括上下移动、放大缩小、旋转等功能。通过代码示例演示了如何使用ObjectAnimator和AnimatorSet来实现动画效果,并提供了实现抖动效果的代码。同时还介绍了如何使用translationY和translationX来实现上下和左右移动的效果。最后还提供了一个anim_small.xml文件的代码示例,可以用来实现放大缩小的效果。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文讨论了Alink回归预测的不完善问题,指出目前主要针对Python做案例,对其他语言支持不足。同时介绍了pom.xml文件的基本结构和使用方法,以及Maven的相关知识。最后,对Alink回归预测的未来发展提出了期待。 ... [详细]
  • 本文讲述了如何通过代码在Android中更改Recycler视图项的背景颜色。通过在onBindViewHolder方法中设置条件判断,可以实现根据条件改变背景颜色的效果。同时,还介绍了如何修改底部边框颜色以及提供了RecyclerView Fragment layout.xml和项目布局文件的示例代码。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 本文介绍了在SpringBoot中集成thymeleaf前端模版的配置步骤,包括在application.properties配置文件中添加thymeleaf的配置信息,引入thymeleaf的jar包,以及创建PageController并添加index方法。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • Java验证码——kaptcha的使用配置及样式
    本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
  • Android系统移植与调试之如何修改Android设备状态条上音量加减键在横竖屏切换的时候的显示于隐藏
    本文介绍了如何修改Android设备状态条上音量加减键在横竖屏切换时的显示与隐藏。通过修改系统文件system_bar.xml实现了该功能,并分享了解决思路和经验。 ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • Android开发实现的计时器功能示例
    本文分享了Android开发实现的计时器功能示例,包括效果图、布局和按钮的使用。通过使用Chronometer控件,可以实现计时器功能。该示例适用于Android平台,供开发者参考。 ... [详细]
  • docker增加restart=always, docker重启后自动启动容器的方法
    本文介绍了在运行docker容器时如何添加参数来保证每次docker服务重启后容器也自动重启的方法,以及如何使用命令来更新已启动的容器。 ... [详细]
  • 本文介绍了Hyperledger Fabric外部链码构建与运行的相关知识,包括在Hyperledger Fabric 2.0版本之前链码构建和运行的困难性,外部构建模式的实现原理以及外部构建和运行API的使用方法。通过本文的介绍,读者可以了解到如何利用外部构建和运行的方式来实现链码的构建和运行,并且不再受限于特定的语言和部署环境。 ... [详细]
  • 处理docker容器时间和宿主机时间不一致问题的方法
    本文介绍了处理docker容器时间和宿主机时间不一致问题的方法,包括复制主机的localtime到容器、处理报错情况以及重启容器的步骤。通过这些方法,可以解决docker容器时间和宿主机时间不一致的问题。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
author-avatar
物业美女_959
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有