• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.systemui.charging;
18 
19 import android.content.Context;
20 import android.graphics.Canvas;
21 import android.graphics.Paint;
22 import android.util.AttributeSet;
23 import android.view.View;
24 import android.view.animation.Interpolator;
25 
26 import com.android.settingslib.Utils;
27 import com.android.systemui.Interpolators;
28 import com.android.systemui.R;
29 
30 final class WirelessChargingView extends View {
31 
32     private Interpolator mInterpolator;
33     private float mPathGone;
34     private float mInterpolatedPathGone;
35     private long mAnimationStartTime;
36     private long mScaleDotsDuration;
37 
38     private boolean mFinishedAnimatingDots = false;
39     private int mNumDots;
40 
41     private double mAngleOffset;
42     private double mCurrAngleOffset;
43 
44     private int mDotsRadiusStart;
45     private int mDotsRadiusEnd;
46     private int mCurrDotRadius;
47 
48     private int mMainCircleStartRadius;
49     private int mMainCircleEndRadius;
50     private int mMainCircleCurrentRadius;
51 
52     private int mCenterX;
53     private int mCenterY;
54 
55     private Paint mPaint;
56     private Context mContext;
57 
WirelessChargingView(Context context)58     public WirelessChargingView(Context context) {
59         super(context);
60         init(context, null);
61     }
62 
WirelessChargingView(Context context, AttributeSet attr)63     public WirelessChargingView(Context context, AttributeSet attr) {
64         super(context, attr);
65         init(context, attr);
66     }
67 
WirelessChargingView(Context context, AttributeSet attr, int styleAttr)68     public WirelessChargingView(Context context, AttributeSet attr, int styleAttr) {
69         super(context, attr, styleAttr);
70         init(context, attr);
71     }
72 
init(Context context, AttributeSet attr)73     public void init(Context context, AttributeSet attr) {
74         mContext = context;
75 
76         mDotsRadiusStart = context.getResources().getDimensionPixelSize(
77                 R.dimen.wireless_charging_dots_radius_start);
78         mDotsRadiusEnd = context.getResources().getDimensionPixelSize(
79                 R.dimen.wireless_charging_dots_radius_end);
80 
81         mMainCircleStartRadius = context.getResources().getDimensionPixelSize(
82                 R.dimen.wireless_charging_circle_radius_start);
83         mMainCircleEndRadius = context.getResources().getDimensionPixelSize(
84                 R.dimen.wireless_charging_circle_radius_end);
85         mMainCircleCurrentRadius = mMainCircleStartRadius;
86 
87         mAngleOffset = context.getResources().getInteger(R.integer.wireless_charging_angle_offset);
88         mScaleDotsDuration = (long) context.getResources().getInteger(
89                 R.integer.wireless_charging_scale_dots_duration);
90         mNumDots = context.getResources().getInteger(R.integer.wireless_charging_num_dots);
91 
92         setupPaint();
93         mInterpolator = Interpolators.LINEAR_OUT_SLOW_IN;
94     }
95 
setupPaint()96     private void setupPaint() {
97         mPaint = new Paint();
98         mPaint.setColor(Utils.getColorAttr(mContext, R.attr.wallpaperTextColor));
99     }
100 
setPaintColor(int color)101     public void setPaintColor(int color) {
102         mPaint.setColor(color);
103     }
104 
105     @Override
onDraw(final Canvas canvas)106     protected void onDraw(final Canvas canvas) {
107         super.onDraw(canvas);
108 
109         if (mAnimationStartTime == 0) {
110             mAnimationStartTime = System.currentTimeMillis();
111         }
112 
113         updateDrawingParameters();
114         drawCircles(canvas);
115 
116         if (!mFinishedAnimatingDots) {
117             invalidate();
118         }
119     }
120 
121     /**
122      * Draws a larger circle of radius {@link WirelessChargingView#mMainCircleEndRadius} composed of
123      * {@link WirelessChargingView#mNumDots} smaller circles
124      * @param canvas
125      */
drawCircles(Canvas canvas)126     private void drawCircles(Canvas canvas) {
127         mCenterX = canvas.getWidth() / 2;
128         mCenterY = canvas.getHeight() / 2;
129 
130         // draws mNumDots to compose a larger, main circle
131         for (int circle = 0; circle < mNumDots; circle++) {
132             double angle = ((mCurrAngleOffset) * Math.PI / 180) + (circle * ((2 * Math.PI)
133                     / mNumDots));
134 
135             int x = (int) (mCenterX + Math.cos(angle) * (mMainCircleCurrentRadius +
136                     mCurrDotRadius));
137             int y = (int) (mCenterY + Math.sin(angle) * (mMainCircleCurrentRadius +
138                     mCurrDotRadius));
139 
140             canvas.drawCircle(x, y, mCurrDotRadius, mPaint);
141         }
142 
143         if (mMainCircleCurrentRadius >= mMainCircleEndRadius) {
144             mFinishedAnimatingDots = true;
145         }
146     }
147 
updateDrawingParameters()148     private void updateDrawingParameters() {
149         long now = System.currentTimeMillis();
150         long timeSinceStart = now - mAnimationStartTime;
151         mPathGone = getPathGone(now);
152         mInterpolatedPathGone = mInterpolator.getInterpolation(mPathGone);
153 
154         // Position Dots: update main circle radius (that the dots compose)
155         if (mPathGone < 1.0f) {
156             mMainCircleCurrentRadius = mMainCircleStartRadius + (int) (mInterpolatedPathGone *
157                     (mMainCircleEndRadius - mMainCircleStartRadius));
158         } else {
159             mMainCircleCurrentRadius = mMainCircleEndRadius;
160         }
161 
162         // Scale Dots: update dot radius
163         if (timeSinceStart < mScaleDotsDuration) {
164             mCurrDotRadius = mDotsRadiusStart + (int) (mInterpolator.getInterpolation((float)
165                     timeSinceStart / mScaleDotsDuration) * (mDotsRadiusEnd - mDotsRadiusStart));
166         } else {
167             mCurrDotRadius = mDotsRadiusEnd;
168         }
169 
170         // Rotation Dot Group: dots rotate from 0 to 20 degrees
171         mCurrAngleOffset = mAngleOffset * mPathGone;
172     }
173 
174     /**
175      * @return decimal depicting how far along the creation of the larger circle (of circles) is
176      * For values < 1.0, the larger circle is being drawn
177      * For values > 1.0 the larger circle has been drawn and further animation can occur
178      */
getPathGone(long now)179     private float getPathGone(long now) {
180         return (float) (now - mAnimationStartTime) / (WirelessChargingAnimation.DURATION);
181     }
182 }