私のアニメーションにも同様の問題がありました。アニメーションはバッテリーにとって高価なので、バッテリー節約モードではアニメーションは実行されず、アプリケーションは状態を終了状態にスキップします。 私は、アニメーションを使用しレンダリングした可能性の1つとして、ObjectAnimatorとValueAnimatorをカスタム実装に置き換えることがあります。以下は、反時計回りの方向に塗りつぶすアニメーションのカスタムサークルビューの例です。このアニメーションはバッテリー節約モードで発生します。
基本的には、アニメーションの長さを知り、1秒ごとに描画する割合を知っているので、描画してからキャンバスをクリアし、次の秒に描画の割合を描画します。これは、キャンバスをクリアして終了状態を保持しない最終状態に達するまで発生します。主な部分は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() {
}
});