22
33import android .animation .ValueAnimator ;
44import android .content .Context ;
5+ import android .graphics .Bitmap ;
6+ import android .graphics .BitmapFactory ;
57import android .graphics .Canvas ;
68import android .graphics .Color ;
79import android .graphics .Paint ;
10+ import android .graphics .Path ;
11+ import android .graphics .Rect ;
12+ import android .graphics .RectF ;
13+ import android .os .Build ;
814import android .support .annotation .Nullable ;
15+ import android .support .annotation .RequiresApi ;
16+ import android .support .v7 .widget .ViewUtils ;
917import android .util .AttributeSet ;
18+ import android .util .TypedValue ;
1019import android .view .View ;
1120import android .view .animation .DecelerateInterpolator ;
1221
22+ import com .allen .androidcustomview .R ;
23+
24+ import java .text .DecimalFormat ;
25+
1326/**
1427 * Created by Allen on 2017/5/14.
1528 * <p>
1831
1932public class HorizontalProgressBar extends View {
2033
34+
2135 private Paint bgPaint ;
2236 private Paint progressPaint ;
2337
38+ private Paint tipPaint ;
39+ private Paint textPaint ;
40+
2441 private int width ;
2542 private int height ;
2643 /**
@@ -41,7 +58,7 @@ public class HorizontalProgressBar extends View {
4158 /**
4259 * 动画执行时间
4360 */
44- private int duration = 2000 ;
61+ private int duration = 1000 ;
4562 /**
4663 * 动画延时启动时间
4764 */
@@ -51,16 +68,44 @@ public class HorizontalProgressBar extends View {
5168 private ProgressListener progressListener ;
5269
5370
71+ private Path path = new Path ();
72+
73+ private int strokeWidth = 5 ;
74+
75+ private int tipHeight = 50 ;
76+ private int tipWidth = 100 ;
77+
78+ private int dis = 10 ;
79+
80+
81+ private float move ;
82+
83+ private Rect textRect = new Rect ();
84+ private String textString ;
85+
86+ private int bgColor = 0xFFe1e5e8 ;
87+
88+ private int progressColor = 0xFFf66b12 ;
89+
90+ private RectF rectF = new RectF ();
5491 public HorizontalProgressBar (Context context ) {
5592 super (context );
5693 }
5794
5895 public HorizontalProgressBar (Context context , @ Nullable AttributeSet attrs ) {
5996 super (context , attrs );
6097
61- bgPaint = getPaint (10 , Color .GRAY );
62- progressPaint = getPaint (10 , Color .RED );
98+ bgPaint = getPaint (strokeWidth , bgColor );
99+ progressPaint = getPaint (strokeWidth , progressColor );
100+
101+ tipPaint = getPaint (1 , progressColor );
102+ tipPaint .setStyle (Paint .Style .FILL );
63103
104+ textPaint = new Paint (Paint .ANTI_ALIAS_FLAG );
105+ textPaint .setTextSize (20 );
106+ textPaint .setColor (Color .WHITE );
107+ textPaint .setTextAlign (Paint .Align .CENTER );
108+ textPaint .setAntiAlias (true );
64109 }
65110
66111 private Paint getPaint (int strokeWidth , int color ) {
@@ -74,6 +119,39 @@ private Paint getPaint(int strokeWidth, int color) {
74119 return paint ;
75120 }
76121
122+ @ Override
123+ protected void onMeasure (int widthMeasureSpec , int heightMeasureSpec ) {
124+ // super.onMeasure(widthMeasureSpec, heightMeasureSpec);
125+ setMeasuredDimension (measureWidth (widthMeasureSpec ), measureHeight (heightMeasureSpec ));
126+ }
127+
128+ private int measureWidth (int measureSpec ) {
129+ int specMode = MeasureSpec .getMode (measureSpec );
130+ int specSize = MeasureSpec .getSize (measureSpec );
131+ //设置一个默认值,就是这个View的默认宽度为500,这个看我们自定义View的要求
132+ int result = 300 ;
133+ if (specMode == MeasureSpec .AT_MOST ) {//相当于我们设置为wrap_content
134+ result = specSize ;
135+ } else if (specMode == MeasureSpec .EXACTLY ) {//相当于我们设置为match_parent或者为一个具体的值
136+ result = specSize ;
137+ }
138+ return result ;
139+ }
140+
141+ private int measureHeight (int measureSpec ) {
142+ int specMode = MeasureSpec .getMode (measureSpec );
143+ int specSize = MeasureSpec .getSize (measureSpec );
144+ int result = 100 ;
145+ if (specMode == MeasureSpec .AT_MOST ) {
146+ result = specSize ;
147+ } else if (specMode == MeasureSpec .EXACTLY ) {
148+ result = specSize ;
149+ }
150+ return result ;
151+ }
152+
153+
154+
77155 @ Override
78156 protected void onSizeChanged (int w , int h , int oldw , int oldh ) {
79157 super .onSizeChanged (w , h , oldw , oldh );
@@ -87,11 +165,76 @@ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
87165 protected void onDraw (Canvas canvas ) {
88166 super .onDraw (canvas );
89167
90- canvas .drawLine (0 , getHeight () / 2 , getWidth (), getHeight () / 2 , bgPaint );
168+ // canvas.drawLine(getPaddingLeft(), getHeight()-strokeWidth , getWidth(), getHeight()-strokeWidth , bgPaint);
169+ //
170+ // canvas.drawLine(getPaddingLeft(), getHeight()-strokeWidth , currentProgress, getHeight()-strokeWidth , progressPaint);
171+
172+ canvas .drawLine (getPaddingLeft (), tipHeight +20 , getWidth (), tipHeight +20 , bgPaint );
173+
174+ canvas .drawLine (getPaddingLeft (), tipHeight +20 , currentProgress , tipHeight +20 , progressPaint );
175+
176+ // drawTipPath(canvas,move);
177+ drawTipView (canvas );
178+
179+ drawText (canvas ,textString );
180+
181+ }
182+
183+ private void drawTipPath (Canvas canvas , int move ) {
184+ path .moveTo (0 +move ,0 );
185+ path .lineTo (0 +move , tipHeight );
186+ path .lineTo ((tipWidth -dis )/2 +move , tipHeight );
187+ path .lineTo ((tipWidth -dis )/2 +dis /2 +move , tipHeight +5 );
188+ path .lineTo ((tipWidth -dis )/2 +dis +move , tipHeight );
189+ path .lineTo (tipWidth +move , tipHeight );
190+ path .lineTo (tipWidth +move ,0 );
191+ path .close ();
192+
193+ drawTipView (canvas );
194+
91195
92- canvas . drawLine ( 0 , getHeight () / 2 , currentProgress , getHeight () / 2 , progressPaint );
196+ path . reset ( );
93197 }
94198
199+ private void drawTipView (Canvas canvas ) {
200+ drawRoundRect (canvas );
201+
202+ drawTriangle (canvas );
203+ }
204+
205+
206+ private void drawRoundRect (Canvas canvas ) {
207+
208+ rectF .set (move ,0 , tipWidth +move , tipHeight );
209+ canvas .drawRoundRect (rectF ,5 ,5 ,tipPaint );
210+ canvas .drawPath (path ,tipPaint );
211+
212+ }
213+
214+ private void drawTriangle (Canvas canvas ) {
215+ path .moveTo (tipWidth /2 -dis +move , tipHeight );
216+ path .lineTo (tipWidth /2 +move , tipHeight +dis );
217+ path .lineTo (tipWidth /2 +dis +move , tipHeight );
218+ canvas .drawPath (path ,tipPaint );
219+ path .reset ();
220+
221+ }
222+
223+ /**
224+ * 绘制文字
225+ *
226+ * @param canvas 画布
227+ */
228+ private void drawText (Canvas canvas , String textString ) {
229+ textRect .left = (int ) move ;
230+ textRect .top = 0 ;
231+ textRect .right = (int ) (tipWidth +move );
232+ textRect .bottom = tipHeight ;
233+ Paint .FontMetricsInt fontMetrics = textPaint .getFontMetricsInt ();
234+ int baseline = (textRect .bottom + textRect .top - fontMetrics .bottom - fontMetrics .top ) / 2 ;
235+ //文字绘制到整个布局的中心位置
236+ canvas .drawText (textString +"%" , textRect .centerX (), baseline , textPaint );
237+ }
95238
96239 private void initAnimation () {
97240 progressAnimator = ValueAnimator .ofFloat (0 , mProgress );
@@ -102,11 +245,14 @@ private void initAnimation() {
102245 @ Override
103246 public void onAnimationUpdate (ValueAnimator valueAnimator ) {
104247 float value = (float ) valueAnimator .getAnimatedValue ();
105-
248+ textString = formatNum ( value );
106249 currentProgress = value * width / 100 ;
107250 if (progressListener != null ) {
108251 progressListener .currentProgressListener (value );
109252 }
253+ if (currentProgress >=(tipWidth /2 )&¤tProgress <=(width - tipWidth /2 )){
254+ move = currentProgress - tipWidth /2 ;
255+ }
110256 invalidate ();
111257
112258 }
@@ -125,10 +271,12 @@ public void startProgressAnimation() {
125271 progressAnimator .start ();
126272 }
127273
274+ @ RequiresApi (api = Build .VERSION_CODES .KITKAT )
128275 public void pauseProgressAnimation () {
129276 progressAnimator .pause ();
130277 }
131278
279+ @ RequiresApi (api = Build .VERSION_CODES .KITKAT )
132280 public void resumeProgressAnimation () {
133281 progressAnimator .resume ();
134282 }
@@ -145,5 +293,48 @@ public HorizontalProgressBar setProgressListener(ProgressListener listener) {
145293 progressListener = listener ;
146294 return this ;
147295 }
296+ /**
297+ * 格式化数字(保留两位小数)
298+ * @param money
299+ * @return
300+ */
301+ public static String formatNumTwo (double money ) {
302+ DecimalFormat format = new DecimalFormat ("0.00" );
303+ return format .format (money );
304+ }
305+
306+ /**
307+ * 格式化数字(保留两位小数)
308+ * @param money
309+ * @return
310+ */
311+ public static String formatNum (float money ) {
312+ DecimalFormat format = new DecimalFormat ("0" );
313+ return format .format (money );
314+ }
315+
316+ /**
317+ * dp 2 px
318+ *
319+ * @param dpVal
320+ */
321+ protected int dp2px (int dpVal )
322+ {
323+ return (int ) TypedValue .applyDimension (TypedValue .COMPLEX_UNIT_DIP ,
324+ dpVal , getResources ().getDisplayMetrics ());
325+ }
326+
327+ /**
328+ * sp 2 px
329+ *
330+ * @param spVal
331+ * @return
332+ */
333+ protected int sp2px (int spVal )
334+ {
335+ return (int ) TypedValue .applyDimension (TypedValue .COMPLEX_UNIT_SP ,
336+ spVal , getResources ().getDisplayMetrics ());
337+
338+ }
148339
149340}
0 commit comments