我的所有 Android 动画都被跳过

All of my Android animations are skipped

我在 Android 上创建的游戏有问题。

我的游戏使用了很多 ObjectAnimatorValueAnimatorThread

一些用户尝试了一个导致游戏无法播放的问题:所有动画都被跳过

当 Stamina 模式(在我的 Xperia Z3 上)被激活时,我可以重现这个错误,但一些用户在 S7 Edge 上也有这个错误。有关信息,Stamina 模式是所有 Xperia 手机都包含的省电模式。

如何防止这个错误?

我的动画也有类似的问题。动画对电池的消耗很大,因此在节电模式下,动画不会执行,应用会跳到结束状态。 我已经使用并渲染动画的一种可能性是用自定义实现替换 ObjectAnimator 和 ValueAnimator。以下是我设置动画以逆时针方向填充的自定义圆形视图的示例。此动画发生在节电模式下。

基本上,我找出动画的持续时间,然后我知道每秒要完成的绘图百分比,我绘制它然后清除 canvas 然后绘制百分比下一秒就画好了这种情况一直发生到我到达结束状态,此时我没有清除 canvas 并保留结束状态。主要部分是 onDraw 方法。

public class AnimatedCircleView extends View {
  private Interpolator INTERPOLATOR = new AccelerateDecelerateInterpolator();

  @IntDef({START, END, ANIMATING})
  @Retention(RetentionPolicy.SOURCE)
  public @interface State {
  }

  private static final int START = 0;
  private static final int END = 1;
  private static final int ANIMATING = 2;

  private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
  private final RectF mRect = new RectF();

  @State private int mState = START;
  private long mAnimationStartTime = 0;
  private long mDuration = 0;
  private Listener mListener = null;

  public AnimatedCircleView(Context context) {
    super(context);
  }

  public AnimatedCircleView(Context context, AttributeSet attrs) {
    super(context, attrs);
  }

  public void startCircleAnimation(long durationMillis, Listener listener) {
    mDuration = durationMillis;
    mAnimationStartTime = System.currentTimeMillis();
    mState = ANIMATING;
    mListener = listener;
    invalidate();
  }

  @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    mRect.left = 0;
    mRect.right = w;
    mRect.top = 0;
    mRect.bottom = h;
  }

  @Override protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    if (mState == START) {
      // Draw nothing.
      return;
    }

    float percentToDraw;
    if (mState == ANIMATING) {
      float currentAnimationTime = System.currentTimeMillis() - mAnimationStartTime;//Get how much animation time is remaining
      float percentAnimationTime = currentAnimationTime / mDuration;//So now you how much percent you need to draw
      if (percentAnimationTime >= 1f) { //If percent is greater than 100%, you have reached the end
        percentToDraw = 1f;
        mState = END;
        if (mListener != null) mListener.onAnimationEnd();
      } else {
        percentToDraw = INTERPOLATOR.getInterpolation(percentAnimationTime);//Else apply the interpolator
      }
    } else {
      // END state
      percentToDraw = 1f;
    }
    float sweepValue = 360f * percentToDraw; //Multiply the final value of the filled circle with percentToDraw, so you know how much to draw.
    float sweepAngle = -sweepValue; //Draw anti clockwise
    canvas.drawArc(mRect, -90, sweepAngle, false, mPaint); //Draw on canvas

    if (mState == ANIMATING) {
      postInvalidateOnAnimation(); // Clear the drawing as animation is happening
    }
  }

  public interface Listener {
    void onAnimationEnd();
  }
}

在您的 xml 中包含此自定义视图,如下所示:

<com.example.sunny.BatteryCircle.AnimatedCircleView
        android:id="@+id/cvAnimatedCircleView"
        android:layout_centerVertical="true"
        android:layout_width="45dp"
        android:layout_height="45dp" />

现在您可以从 activity 中调用动画,如下所示:

AnimatedCircleView animatedCircleView = (AnimatedCircleView) findViewById(R.id.cvAnimatedCircleView);
        animatedCircleView.startCircleAnimation(2000, new AnimatedCircleView.Listener() {
            @Override public void onAnimationEnd() {
            }
        });