• Android 逐帧动画isRunning 一直返回true的问题


    AnimationDrawabl主要通过xml实现逐帧动画,SDK实例如下:

    An AnimationDrawable defined in XML consists of a single <animation-list> element, and a series of nested <item> tags. Each item defines a frame of the animation. See the example below. 
    
    spin_animation.xml file in res/drawable/ folder:
    
    <!-- Animation frames are wheel0.png -- wheel5.png files inside the
     res/drawable/ folder -->
     <animation-list android:id="selected" android:oneshot="false">
        <item android:drawable="@drawable/wheel0" android:duration="50" />
        <item android:drawable="@drawable/wheel1" android:duration="50" />
        <item android:drawable="@drawable/wheel2" android:duration="50" />
        <item android:drawable="@drawable/wheel3" android:duration="50" />
        <item android:drawable="@drawable/wheel4" android:duration="50" />
        <item android:drawable="@drawable/wheel5" android:duration="50" />
     </animation-list>Here is the code to load and play this animation.
    
     // Load the ImageView that will host the animation and
     // set its background to our AnimationDrawable XML resource.
     ImageView img = (ImageView)findViewById(R.id.spinning_wheel_image);
     img.setBackgroundResource(R.drawable.spin_animation);
    
     // Get the background, which has been compiled to an AnimationDrawable object.
     AnimationDrawable frameAnimation = (AnimationDrawable) img.getBackground();
    
     // Start the animation (looped playback by default).
     frameAnimation.start();

    例子很简单,清楚,现在说说遇到的一个问题

    最近遇到一个问题,就是设计了一个逐帧动画,但是oneshot=true,这样的话,当调用AnimationDrawable.start()的方法以后,就只播放一次。

    但是我不希望在动画没有结束前,start()被重复调用,因此:

    if(!mAnimation.isRunning()){
          mAnimation.start();  
    }
    

    我在start方法前加了一个判定条件,就是当前不处于isRunning状态时再播放。

    但是问题出现了,当我下次触发,需要调用到start方法是,isRunning始终返回true;

    后来我查阅源码,跟网上资料,得出结论如下:

    首先看看isRunning()

          /**
             * <p>Indicates whether the animation is currently running or not.</p>
             *
             * @return true if the animation is running, false otherwise
             */
            public boolean isRunning() {
                return mCurFrame > -1;
            }

    这里的mCurFrame是当前播放那一帧,当oneshot=true时,播放完成后,停留在最后一帧,也就是此时的mCurFrame保存的是最后一帧的序号,因此,当我们此时调用isRunning()的时候始终返回为true;

    那么如何使得isRunning返回false呢?我们来看看stop方法:

    /**
             * <p>Stops the animation. This method has no effect if the animation is
             * not running.</p>
            *
             * @see #isRunning()
            * @see #start()
             */
            public void stop() {
                if (isRunning()) {
                    unscheduleSelf(this);
               }
           }
            @Override
            public void unscheduleSelf(Runnable what) {
                mCurFrame = -1;
                super.unscheduleSelf(what);
            }

        我们看到调用stop方法时,会间接的将mCurFrame = -1;

          现在我们回头想先oneShot的含义是完整的播放一次动画,并不是我们理解的动画播放一次,而是只从start 到stop,才算是完整的一次动画,因此android将stop的方法开放给用户,让用户自行控制oneshot的周期。

          所以要解决最开始的问题,一定要手动显式的调用一次stop方法就可以了,具体的,要自己定义一个延时,比如handler或者timer都可以。

  • 相关阅读:
    【vim使用】替换文本
    Ubuntu中将vim中查找设置为高亮
    【vim使用】查找文本
    【vim使用】缩进 和 重复执行上一次命令
    【vim使用】替换命令
    【vim使用】复制和粘贴
    【vim使用】撤销和恢复撤销
    【vim使用】删除文本
    【vim使用】选中文本(可视模式)
    【vim使用】利用标记返回之前需要编辑的代码位置
  • 原文地址:https://www.cnblogs.com/qgli/p/3311978.html
Copyright © 2020-2023  润新知