我在Android上创建的游戏存在问题。
我的游戏正在使用大量 ObjectAnimator , ValueAnimator 和线程。
有些用户尝试了一个让游戏无法播放的问题:跳过所有动画。
当Stamina模式(在我的Xperia Z3上)被激活时,我可以重现这个错误,但是一些用户也有S7 Edge的这个错误。有关信息,Stamina模式是所有Xperia手机中都包含的节电器。
如何防止此错误?
答案 0 :(得分:1)
我的动画也有类似的问题。动画对于电池来说是昂贵的,因此在节电模式下,动画不会被执行并且应用程序会将状态跳到最终状态。 我使用并确实渲染动画的一种可能性是用自定义实现替换ObjectAnimator和ValueAnimator。以下是我以逆时针方向填充的自定义圆形视图的示例。此动画在节电模式下发生。
基本上,我发现动画的持续时间是什么,然后我知道每秒要完成的绘图百分比,我绘制然后清除画布然后在下一秒绘制绘图的百分比。这种情况发生,直到我到达结束状态,当我不清除画布并保持结束状态。主要部分是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" />
现在您可以按如下方式从活动中调用动画:
AnimatedCircleView animatedCircleView = (AnimatedCircleView) findViewById(R.id.cvAnimatedCircleView);
animatedCircleView.startCircleAnimation(2000, new AnimatedCircleView.Listener() {
@Override public void onAnimationEnd() {
}
});