blob: f5edf5216fa25d492fc3452e720ac94f0f6cf7bf [file] [log] [blame]
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.charging;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import com.android.settingslib.Utils;
import com.android.systemui.R;
final class WirelessChargingView extends View {
private Interpolator mInterpolator;
private float mPathGone;
private float mInterpolatedPathGone;
private long mAnimationStartTime;
private long mStartSpinCircleAnimationTime;
private long mAnimationOffset = 500;
private long mTotalAnimationDuration = WirelessChargingAnimation.DURATION - mAnimationOffset;
private long mExpandingCircle = (long) (mTotalAnimationDuration * .9);
private long mSpinCircleAnimationTime = mTotalAnimationDuration - mExpandingCircle;
private boolean mFinishedAnimatingSpinningCircles = false;
private int mStartAngle = -90;
private int mNumSmallCircles = 20;
private int mSmallCircleRadius = 10;
private int mMainCircleStartRadius = 100;
private int mMainCircleEndRadius = 230;
private int mMainCircleCurrentRadius = mMainCircleStartRadius;
private int mCenterX;
private int mCenterY;
private Paint mPaint;
private Context mContext;
public WirelessChargingView(Context context) {
super(context);
init(context, null);
}
public WirelessChargingView(Context context, AttributeSet attr) {
super(context, attr);
init(context, attr);
}
public WirelessChargingView(Context context, AttributeSet attr, int styleAttr) {
super(context, attr, styleAttr);
init(context, attr);
}
public void init(Context context, AttributeSet attr) {
mContext = context;
setupPaint();
mInterpolator = new DecelerateInterpolator();
}
private void setupPaint() {
mPaint = new Paint();
mPaint.setColor(Utils.getColorAttr(mContext, R.attr.wallpaperTextColor));
}
@Override
protected void onDraw(final Canvas canvas) {
super.onDraw(canvas);
if (mAnimationStartTime == 0) {
mAnimationStartTime = System.currentTimeMillis();
}
updateDrawingParameters();
drawCircles(canvas);
if (!mFinishedAnimatingSpinningCircles) {
invalidate();
}
}
/**
* Draws a larger circle of radius {@link WirelessChargingView#mMainCircleEndRadius} composed of
* {@link WirelessChargingView#mNumSmallCircles} smaller circles
* @param canvas
*/
private void drawCircles(Canvas canvas) {
mCenterX = canvas.getWidth() / 2;
mCenterY = canvas.getHeight() / 2;
// angleOffset makes small circles look like they're moving around the main circle
float angleOffset = mPathGone * 10;
// draws mNumSmallCircles to compose a larger, main circle
for (int circle = 0; circle < mNumSmallCircles; circle++) {
double angle = ((mStartAngle + angleOffset) * Math.PI / 180) + (circle * ((2 * Math.PI)
/ mNumSmallCircles));
int x = (int) (mCenterX + Math.cos(angle) * (mMainCircleCurrentRadius +
mSmallCircleRadius));
int y = (int) (mCenterY + Math.sin(angle) * (mMainCircleCurrentRadius +
mSmallCircleRadius));
canvas.drawCircle(x, y, mSmallCircleRadius, mPaint);
}
if (mMainCircleCurrentRadius >= mMainCircleEndRadius && !isSpinCircleAnimationStarted()) {
mStartSpinCircleAnimationTime = System.currentTimeMillis();
}
if (isSpinAnimationFinished()) {
mFinishedAnimatingSpinningCircles = true;
}
}
private boolean isSpinCircleAnimationStarted() {
return mStartSpinCircleAnimationTime != 0;
}
private boolean isSpinAnimationFinished() {
return isSpinCircleAnimationStarted() && System.currentTimeMillis() -
mStartSpinCircleAnimationTime > mSpinCircleAnimationTime;
}
private void updateDrawingParameters() {
mPathGone = getPathGone(System.currentTimeMillis());
mInterpolatedPathGone = mInterpolator.getInterpolation(mPathGone);
if (mPathGone < 1.0f) {
mMainCircleCurrentRadius = mMainCircleStartRadius + (int) (mInterpolatedPathGone *
(mMainCircleEndRadius - mMainCircleStartRadius));
} else {
mMainCircleCurrentRadius = mMainCircleEndRadius;
}
}
/**
* @return decimal depicting how far along the creation of the larger circle (of circles) is
* For values < 1.0, the larger circle is being drawn
* For values > 1.0 the larger circle has been drawn and further animation can occur
*/
private float getPathGone(long now) {
return (float) (now - mAnimationStartTime) / (mExpandingCircle);
}
}