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®ion) != 0) { 178 return WHITE_COLOR; 179 } 180 if ((mColoredRegions®ion) == 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 }