今天的文章里,我将会和大家讨论对动画流的控制。我们可以通过Animator系列的API来控制动画的开始、停止和取消。在 KitKat也就是API level 19中,我们还可以控制动画的暂停和恢复。在本文中,我将会带你体验整个动画流的控制,并且通过一些函数方法来让你能够观察到动画的状态。

动画流介绍

在之前的教程中,我们已经使用过多次Animator.start这个方法。这个方法是用来让动画从第一帧开始播放。该方法只是动画流控制方法集中的一个方法而已,完整的方法集合如下所示:

Java
; html-script: false ]
Animator.start() // start the animation from the beginning
Animator.end() // end the animation
Animator.cancel() // cancel the animation
Animator.pause() // added in API 19; pause the animation
Animator.resume() // added in API 19; resume a paused animation
1
2
3
4
5
6
; html-script: false ]
Animator.start()   // start the animation from the beginning
Animator.end()     // end the animation
Animator.cancel()  // cancel the animation
Animator.pause()   // added in API 19; pause the animation
Animator.resume()  // added in API 19; resume a paused animation

start这个方法顾名思义是用来让动画从开头开始播放的。如果动画设置了一个大于0的播放延迟(startDelay),那么调用该方法后还需要等到延迟的时间过去才回开始播放。
我们有两种停止动画的方法,你可以用end方法抑或cancel方法来停止一个播放着的动画。在两种方式中动画都会终止并且只有再次调用start方法才会重新开始播放。两者的区别则在于停止后动画所在的状态,当你使用cancel方法来停止动画后,动画只是停止了它的时间轴,动画的状态会停在一个中间态(intermediate
state)。如果通过end 方法来停止一个动画,那么动画会直接快进到该动画最后一帧并且停止,所有的对象都会保持在动画最终结束后的状态。
在 Kitkat
中增加的没有怎么被大家关注到的新API则是带来了动画可以暂停和恢复的能力。在那之前,一个动画如果被取消并且停留在当前的中间态,此时你用start方法去重启动画,动画只会从一开始重新播放。现在,你则可以调用pause方法来暂停当前播放中的动画,pause也会有和cancel方法一样的功效让动画停留在中间态,但是当你使用resume
方法去恢复这个动画的时候,动画会从这个状态继续播放下去。
现在,让我们来实践下看看效果。我们新建一个 Activity 并且包含一个 私有的动画对象。并且在 onCreate 回调中初始化这个动画。

Java
; html-script: false ]
private ObjectAnimator anim;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.property_animations_flow);

ImageView someImage = (ImageView) findViewById(R.id.some_image);

anim = ObjectAnimator.ofFloat(someImage, "rotation", 0, 360);
anim.setDuration(1000);
anim.setRepeatCount(5);
anim.setRepeatMode(ObjectAnimator.RESTART);
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
; html-script: false ]
private ObjectAnimator anim;
 
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.property_animations_flow);
 
    ImageView someImage = (ImageView) findViewById(R.id.some_image);
 
    anim = ObjectAnimator.ofFloat(someImage, "rotation", 0, 360);
    anim.setDuration(1000);
    anim.setRepeatCount(5);
    anim.setRepeatMode(ObjectAnimator.RESTART);
  }

我们的动画是一个简单的旋转动画,它将把一个图片完整旋转360度五次。被旋转的图片会在 layout 的 XML 文件中定义好,并且给予一个叫some_image的id。这个layout同时也包含了五个按钮分别是:Start、End、Cancel、Pause以及Resume。这五个按钮分别代表了动画的五个调用方法。

Java
; html-script: false ]
public void startAnimation(View view) {
anim.start();
}

public void endAnimation(View view) {
anim.end();
}

public void cancelAnimation(View view) {
anim.cancel();
}

public void pauseAnimation(View view) {
anim.pause();
}

public void resumeAnimation(View view) {
anim.resume();
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
; html-script: false ]
  public void startAnimation(View view) {
    anim.start();
  }
 
  public void endAnimation(View view) {
    anim.end();
  }
 
  public void cancelAnimation(View view) {
    anim.cancel();
  }
 
  public void pauseAnimation(View view) {
    anim.pause();
  }
 
  public void resumeAnimation(View view) {
    anim.resume();
  }

这些方法只是简单的调用了相应的动画控制调用。下面会有两张gif图片来演示效果。上边的动画展示了end方法和cancel方法的区别。可以注意到,cancel让图片保持在停止时的中间态,但是end则让动画到了最后的状态。
下边的动画则演示了pause和resume方法。可以注意到,pause 和cancel都暂停了动画的时间轴。但是现在我们可以用resume 调用去恢复动画的时间轴了。

动画状态的查询

有些时候,我们需要去查询当前动画的状态,这个需求可以通过下面这些方法来完成。

Java
; html-script: false ]
boolean isStarted() // added in API 14
boolean isRunning()
boolean isPaused() // added in API 19
1
2
3
4
; html-script: false ]
  boolean isStarted()  // added in API 14
  boolean isRunning()
  boolean isPaused()   // added in API 19

如果当前动画已经调用了start函数并且还没播放完成也没有被取消掉,那么isStarted方法会返回true。请注意,isStarted 方法最低的 API 需求是 14.同时,就算是在动画播放延迟中,该方法依然会返回 true。这就是这个方法和 isRunning 方法的不同点,isRunning 方法只会在动画确实在播放并且还没停止的时候返回 true。

在 API 19 的时候,isPaused 方法被加入进来。这是由于那时候动画可以被暂停和恢复了,如果 isPaused 返回了 true,那么说明当前动画是在暂停状态下,反之亦然。

为了演示这些观察方法的效果,我们会通过一个包含三个显示动画状态文本框的例子来解释。这三个文本框都会在Activity中做为TextView成员变量存在。

Java
; html-script: false ]
private TextView isStartedText;
private TextView isRunningText;
private TextView isPausedText;
1
2
3
4
; html-script: false ]
    private TextView isStartedText;
    private TextView isRunningText;
    private TextView isPausedText;

于此同时,我们在onCreate中添加下列三行代码来把这些文本框从layout中获取到。

Java
; html-script: false ]
isStartedText = (TextView) findViewById(R.id.status_is_started);
isRunningText = (TextView) findViewById(R.id.status_is_running);
isPausedText = (TextView) findViewById(R.id.status_is_paused);
1
2
3
4
; html-script: false ]
    isStartedText = (TextView) findViewById(R.id.status_is_started);
    isRunningText = (TextView) findViewById(R.id.status_is_running);
    isPausedText = (TextView) findViewById(R.id.status_is_paused);

我们还创建了一个根据当前动画状态来更新这些文本框的方法。

Java
; html-script: false ]
public void setStatusTexts() {
isStartedText.setText("isStarted = " + anim.isStarted());
isRunningText.setText("isRunning = " + anim.isRunning());
isPausedText.setText("isPaused = " + anim.isPaused());
}
1
2
3
4
5
6
; html-script: false ]
  public void setStatusTexts() {
    isStartedText.setText("isStarted = " + anim.isStarted());
    isRunningText.setText("isRunning = " + anim.isRunning());
    isPausedText.setText("isPaused = " + anim.isPaused());
  }

我们在初始化以后每次修改动画流的时候都去调用setStatusTexts方法,比如说,当我没调用cancelAnimation的时候,代码是这样的:

Java
; html-script: false ]
public void cancelAnimation(View view) {
anim.cancel();
setStatusTexts();
}
1
2
3
4
5
; html-script: false ]
  public void cancelAnimation(View view) {
    anim.cancel();
    setStatusTexts();
  }

演示的结果我们可以从下面上方的动画中看到。这里我也创建了两个动画,一个演示End和cancel效果,另一个演示pause和 Resume效果。可以注意到,动画的运行状态在你点击了End和cancel之后是相同的,就算视觉上看两者并不一样。这说明了,你没法通过动画的状态来区分出当前动画是通过 End 调用还是cancel调用来停止的。这两者情况下,isStarted和isRunning都会返回false。

而下边的动画则显示了pause和resume调用的效果。当我们通过pause调用去暂停动画时,isPaused会返回true。然后通过 resume调用去恢复动画播放后,isPaused也会变成false。可以注意到,图中如果动画是自然结束的,动画的状态并没有改变。当然,动画停止播放后,isStarted和isRunning肯定应该是返回false的。实际上,在动画自然停止后,如果我们再去调用 isStarted和isRunning他们的的确确会返回false。而动画中的例子我们并没有在动画自然停止后去更新状态,所以我们并不知道当前的状态,自然那几个文本框也就没有更新。为了能够更新到最新的状态,我们可以在动画中添加AnimatorListener和 AnimatorPauseListener这两个监听,这两个监听具体的使用方法会是下一讲的主要内容。

如果你对教程中的例子有兴趣,欢迎去 GitHub 上下载完整代码。

Android属性动画:动画流控制的更多相关文章

  1. Android属性动画

    这几天看郭神的博客 Android属性动画完全解析(上),初识属性动画的基本用法之后,我自己突然想实现一种动画功能,就是我们在携程网.阿里旅行等等手机APP端买火车票的时候,看到有选择城市,那么就有出 ...

  2. Android属性动画源代码解析(超详细)

    本文假定你已经对属性动画有了一定的了解,至少使用过属性动画.下面我们就从属性动画最简单的使用开始. ObjectAnimator .ofInt(target,propName,values[]) .s ...

  3. 【转】android 属性动画之 ObjectAnimator

    原文网址:http://blog.csdn.net/feiduclear_up/article/details/39255083 前面一篇博客讲解了 android 简单动画之 animtion,这里 ...

  4. Android属性动画之ValueAnimation

    ValueAnimation是ObjectAnimation类的父类,经过前几天的介绍,相信大家对ObjectAnimation有了 一定的认识,今天就为大家最后介绍一下ValueAnimation, ...

  5. Android属性动画之ObjectAnimator

    相信对于Android初学者,对于Android中的动画效果一定很感兴趣,今天为大家总结一下刚刚学到的属性动画案例. 首先和一般的Android应用一样,我们先建一个工程,为了方便,我们的布局文件中就 ...

  6. Android属性动画完全解析(下)

    转载:http://blog.csdn.net/guolin_blog/article/details/44171115 大家好,欢迎继续回到Android属性动画完全解析.在上一篇文章当中我们学习了 ...

  7. Android属性动画完全解析(上),初识属性动画的基本用法

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/43536355 在手机上去实现一些动画效果算是件比较炫酷的事情,因此Android系 ...

  8. Android 属性动画(Property Animation) 完全解析 (上)

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38067475 1.概述 Android提 供了几种动画类型:View Anima ...

  9. Android属性动画完全解析(中)

    转载:http://blog.csdn.net/guolin_blog/article/details/43536355 大家好,在上一篇文章当中,我们学习了Android属性动画的基本用法,当然也是 ...

  10. Android属性动画完全解析(上)

    Android属性动画完全解析(上) 转载:http://blog.csdn.net/guolin_blog/article/details/43536355 在手机上去实现一些动画效果算是件比较炫酷 ...

随机推荐

  1. 设计模式之第21章-状态模式(Java实现)

    设计模式之第21章-状态模式(Java实现) “what are you 干啥了?怎么这么萎靡不振?”“昨晚又是补新番,又是补小笼包,睡得有点晚啊.话说杨过的那个雕兄真是太好了,每天给找蛇胆,又陪练武 ...

  2. 图说不为人知的IT传奇故事-2-IBM咬不动的胡桃

    此系列文章为“图说不为人知的IT传奇故事”,各位大忙人可以在一分钟甚至几秒内了解把握整个内容,真可谓“大忙人的福利”呀!!希望各位IT界的朋友在钻研技术的同时,也能在文学.历史上有所把握.了解这些故事 ...

  3. ogre3D学习基础13 -- 键盘控制网格动画mesh

    以上一节为蓝本,这里增加一点难度,添加了四个节点,增加键盘控制移动速度,使用bool变量控制是否移动. 第一,要增加键盘控制,那就使用OIS::KeyListener,在监听器里添加一个父类KeyLi ...

  4. 启用hyper后无法打开vmware

    十万火急,想办法先让虚拟机能够打开,毕竟经常用. 网上看了无数教程都是让在控制面板中关闭hyper-v,然而并没有用. 找了好久说是不能那样关闭,得用指令.管理员运行powershell,输入下列指令 ...

  5. Django框架学习-01Django介绍

    01-Django介绍 02-HTTP协议介绍 01-Django介绍 1.什么是Web框架? 随着Web最新发展趋势的不断升级,Web项目开发也越来越难,而且需要花费更多的开发时间.所以,Web程序 ...

  6. HDU 2440、HDU 3694多边形费马点

    1.http://acm.hdu.edu.cn/showproblem.php?pid=2440   按照题意知道是一个简单的多边形即凸包,但给出的点并没有按照顺序的,所以需要自己先求出凸包,然后在用 ...

  7. 【转】超简单利用UGUI制作圆形小地图

    http://sanwen.net/a/ithhtbo.html 由于UI都是Achor自己用PS做的,比较粗糙,大家见谅,不过丝毫不影响功能的实现,下面我们看看今天的笔记: 首先我们看看需要哪些组件 ...

  8. POJ 3321:Apple Tree(dfs序+树状数组)

    题目大意:对树进行m次操作,有两类操作,一种是改变一个点的权值(将0变为1,1变为0),另一种为查询以x为根节点的子树点权值之和,开始时所有点权值为1. 分析: 对树进行dfs,将树变为序列,记录每个 ...

  9. BZOJ 4569 [Scoi2016]萌萌哒 ——ST表 并查集

    好题. ST表又叫做稀疏表,这里利用了他的性质. 显然每一个条件可以分成n个条件,显然过不了. 然后发现有许多状态是重复的,首先考虑线段树,没什么卵用. 然后ST表,可以每一层表示对应的区间大小的两个 ...

  10. BZOJ 4826 [Hnoi2017]影魔 ——扫描线 单调栈

    首先用单调栈和扫描线处理出每一个数左面最近的比他大的数在$l[i]$,右面最近的比他大的数$r[i]$. 然后就可以考虑每种贡献是在什么时候产生的. 1.$(l[i],r[i])$产生$p1$的贡献 ...