1 /**
2  *
3  */
4 package com.android.settings.applications;
5 
6 import android.content.Context;
7 import android.graphics.Canvas;
8 import android.graphics.LinearGradient;
9 import android.graphics.Paint;
10 import android.graphics.Path;
11 import android.graphics.Rect;
12 import android.graphics.Shader;
13 import android.util.AttributeSet;
14 import android.util.DisplayMetrics;
15 import android.view.MotionEvent;
16 import android.widget.LinearLayout;
17 
18 public class LinearColorBar extends LinearLayout {
19     static final int LEFT_COLOR = 0xff009688;
20     static final int MIDDLE_COLOR = 0xff009688;
21     static final int RIGHT_COLOR = 0xffced7db;
22     static final int GRAY_COLOR = 0xff555555;
23     static final int WHITE_COLOR = 0xffffffff;
24 
25     private float mRedRatio;
26     private float mYellowRatio;
27     private float mGreenRatio;
28 
29     private int mLeftColor = LEFT_COLOR;
30     private int mMiddleColor = MIDDLE_COLOR;
31     private int mRightColor = RIGHT_COLOR;
32 
33     private boolean mShowIndicator = true;
34     private boolean mShowingGreen;
35 
36     private OnRegionTappedListener mOnRegionTappedListener;
37     private int mColoredRegions = REGION_RED | REGION_YELLOW | REGION_GREEN;
38 
39     final Rect mRect = new Rect();
40     final Paint mPaint = new Paint();
41 
42     int mLastInterestingLeft, mLastInterestingRight;
43     int mLineWidth;
44 
45     int mLastLeftDiv, mLastRightDiv;
46     int mLastRegion;
47 
48     final Path mColorPath = new Path();
49     final Path mEdgePath = new Path();
50     final Paint mColorGradientPaint = new Paint();
51     final Paint mEdgeGradientPaint = new Paint();
52 
53     public static final int REGION_RED = 1<<0;
54     public static final int REGION_YELLOW = 1<<1;
55     public static final int REGION_GREEN = 1<<2;
56     public static final int REGION_ALL = REGION_RED | REGION_YELLOW | REGION_GREEN;
57 
58     public interface OnRegionTappedListener {
onRegionTapped(int region)59         public void onRegionTapped(int region);
60     }
61 
LinearColorBar(Context context, AttributeSet attrs)62     public LinearColorBar(Context context, AttributeSet attrs) {
63         super(context, attrs);
64         setWillNotDraw(false);
65         mPaint.setStyle(Paint.Style.FILL);
66         mColorGradientPaint.setStyle(Paint.Style.FILL);
67         mColorGradientPaint.setAntiAlias(true);
68         mEdgeGradientPaint.setStyle(Paint.Style.STROKE);
69         mLineWidth = getResources().getDisplayMetrics().densityDpi >= DisplayMetrics.DENSITY_HIGH
70                 ? 2 : 1;
71         mEdgeGradientPaint.setStrokeWidth(mLineWidth);
72         mEdgeGradientPaint.setAntiAlias(true);
73 
74     }
75 
setOnRegionTappedListener(OnRegionTappedListener listener)76     public void setOnRegionTappedListener(OnRegionTappedListener listener) {
77         if (listener != mOnRegionTappedListener) {
78             mOnRegionTappedListener = listener;
79             setClickable(listener != null);
80         }
81     }
82 
setColoredRegions(int regions)83     public void setColoredRegions(int regions) {
84         mColoredRegions = regions;
85         invalidate();
86     }
87 
setRatios(float red, float yellow, float green)88     public void setRatios(float red, float yellow, float green) {
89         mRedRatio = red;
90         mYellowRatio = yellow;
91         mGreenRatio = green;
92         invalidate();
93     }
94 
setColors(int red, int yellow, int green)95     public void setColors(int red, int yellow, int green) {
96         mLeftColor = red;
97         mMiddleColor = yellow;
98         mRightColor = green;
99         updateIndicator();
100         invalidate();
101     }
102 
setShowIndicator(boolean showIndicator)103     public void setShowIndicator(boolean showIndicator) {
104         mShowIndicator = showIndicator;
105         updateIndicator();
106         invalidate();
107     }
108 
setShowingGreen(boolean showingGreen)109     public void setShowingGreen(boolean showingGreen) {
110         if (mShowingGreen != showingGreen) {
111             mShowingGreen = showingGreen;
112             updateIndicator();
113             invalidate();
114         }
115     }
116 
updateIndicator()117     private void updateIndicator() {
118         int off = getPaddingTop() - getPaddingBottom();
119         if (off < 0) off = 0;
120         mRect.top = off;
121         mRect.bottom = getHeight();
122         if (!mShowIndicator) {
123             return;
124         }
125         if (mShowingGreen) {
126             mColorGradientPaint.setShader(new LinearGradient(
127                     0, 0, 0, off-2, mRightColor &0xffffff, mRightColor, Shader.TileMode.CLAMP));
128         } else {
129             mColorGradientPaint.setShader(new LinearGradient(
130                     0, 0, 0, off-2, mMiddleColor&0xffffff, mMiddleColor, Shader.TileMode.CLAMP));
131         }
132         mEdgeGradientPaint.setShader(new LinearGradient(
133                 0, 0, 0, off/2, 0x00a0a0a0, 0xffa0a0a0, Shader.TileMode.CLAMP));
134     }
135 
136     @Override
onSizeChanged(int w, int h, int oldw, int oldh)137     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
138         super.onSizeChanged(w, h, oldw, oldh);
139         updateIndicator();
140     }
141 
142     @Override
onTouchEvent(MotionEvent event)143     public boolean onTouchEvent(MotionEvent event) {
144         if (mOnRegionTappedListener != null) {
145             switch (event.getAction()) {
146                 case MotionEvent.ACTION_DOWN: {
147                     final int x = (int) event.getX();
148                     if (x < mLastLeftDiv) {
149                         mLastRegion = REGION_RED;
150                     } else if (x < mLastRightDiv) {
151                         mLastRegion = REGION_YELLOW;
152                     } else {
153                         mLastRegion = REGION_GREEN;
154                     }
155                     invalidate();
156                 } break;
157             }
158         }
159         return super.onTouchEvent(event);
160     }
161 
162     @Override
dispatchSetPressed(boolean pressed)163     protected void dispatchSetPressed(boolean pressed) {
164         invalidate();
165     }
166 
167     @Override
performClick()168     public boolean performClick() {
169         if (mOnRegionTappedListener != null && mLastRegion != 0) {
170             mOnRegionTappedListener.onRegionTapped(mLastRegion);
171             mLastRegion = 0;
172         }
173         return super.performClick();
174     }
175 
pickColor(int color, int region)176     private int pickColor(int color, int region) {
177         if (isPressed() && (mLastRegion&region) != 0) {
178             return WHITE_COLOR;
179         }
180         if ((mColoredRegions&region) == 0) {
181             return GRAY_COLOR;
182         }
183         return color;
184     }
185 
186     @Override
onDraw(Canvas canvas)187     protected void onDraw(Canvas canvas) {
188         super.onDraw(canvas);
189 
190         int width = getWidth();
191 
192         int left = 0;
193 
194         int right = left + (int)(width*mRedRatio);
195         int right2 = right + (int)(width*mYellowRatio);
196         int right3 = right2 + (int)(width*mGreenRatio);
197 
198         int indicatorLeft, indicatorRight;
199         if (mShowingGreen) {
200             indicatorLeft = right2;
201             indicatorRight = right3;
202         } else {
203             indicatorLeft = right;
204             indicatorRight = right2;
205         }
206 
207         if (mLastInterestingLeft != indicatorLeft || mLastInterestingRight != indicatorRight) {
208             mColorPath.reset();
209             mEdgePath.reset();
210             if (mShowIndicator && indicatorLeft < indicatorRight) {
211                 final int midTopY = mRect.top;
212                 final int midBottomY = 0;
213                 final int xoff = 2;
214                 mColorPath.moveTo(indicatorLeft, mRect.top);
215                 mColorPath.cubicTo(indicatorLeft, midBottomY,
216                         -xoff, midTopY,
217                         -xoff, 0);
218                 mColorPath.lineTo(width+xoff-1, 0);
219                 mColorPath.cubicTo(width+xoff-1, midTopY,
220                         indicatorRight, midBottomY,
221                         indicatorRight, mRect.top);
222                 mColorPath.close();
223                 final float lineOffset = mLineWidth+.5f;
224                 mEdgePath.moveTo(-xoff+lineOffset, 0);
225                 mEdgePath.cubicTo(-xoff+lineOffset, midTopY,
226                         indicatorLeft+lineOffset, midBottomY,
227                         indicatorLeft+lineOffset, mRect.top);
228                 mEdgePath.moveTo(width+xoff-1-lineOffset, 0);
229                 mEdgePath.cubicTo(width+xoff-1-lineOffset, midTopY,
230                         indicatorRight-lineOffset, midBottomY,
231                         indicatorRight-lineOffset, mRect.top);
232             }
233             mLastInterestingLeft = indicatorLeft;
234             mLastInterestingRight = indicatorRight;
235         }
236 
237         if (!mEdgePath.isEmpty()) {
238             canvas.drawPath(mEdgePath, mEdgeGradientPaint);
239             canvas.drawPath(mColorPath, mColorGradientPaint);
240         }
241 
242         if (left < right) {
243             mRect.left = left;
244             mRect.right = right;
245             mPaint.setColor(pickColor(mLeftColor, REGION_RED));
246             canvas.drawRect(mRect, mPaint);
247             width -= (right-left);
248             left = right;
249         }
250 
251         mLastLeftDiv = right;
252         mLastRightDiv = right2;
253 
254         right = right2;
255 
256         if (left < right) {
257             mRect.left = left;
258             mRect.right = right;
259             mPaint.setColor(pickColor(mMiddleColor, REGION_YELLOW));
260             canvas.drawRect(mRect, mPaint);
261             width -= (right-left);
262             left = right;
263         }
264 
265 
266         right = left + width;
267         if (left < right) {
268             mRect.left = left;
269             mRect.right = right;
270             mPaint.setColor(pickColor(mRightColor, REGION_GREEN));
271             canvas.drawRect(mRect, mPaint);
272         }
273     }
274 }