Android自定义进度条
5901 点击·0 回帖
![]() | ![]() | |
![]() | Android原生控件只有横向进度条一种,而且没法变换样式,比如原生rom的样子 ![]() 很丑是吧,当伟大的产品设计要求更换前背景,甚至纵向,甚至圆弧状的,咋办,比如 ![]() ok,我们开始吧: 一)变换前背景 先来看看progressbar的属性: 1. <ProgressBar 2. Android:id="@+id/progressBar" 3. style="?Android:attr/progressBarStyleHorizontal" 4. Android:layout_width="match_parent" 5. Android:layout_height="wrap_content" 6. Android:layout_margin="5dip" 7. Android:layout_toRightOf="@+id/progressBarV" 8. Android:indeterminate="false" 9. Android:padding="2dip" 10. Android:progress="50" /> 根据style="?Android:attr/progressBarStyleHorizontal",我们找到源码中的style.xml 1. <style name="Widget.ProgressBar.Horizontal"> 2. <item name="Android:indeterminateOnly">false</item> 3. <item name="Android:progressDrawable">@Android:drawable/progress_horizontal</item> 4. <item name="Android:indeterminateDrawable">@Android:drawable/progress_indeterminate_horizontal</item> 5. <item name="Android:minHeight">20dip</item> 6. <item name="Android:maxHeight">20dip</item> 7. </style> 看到 <item name="Android:progressDrawable">@Android:drawable/progress_horizontal</item> 木有,继续发掘源码,找到drawable下面的progress_horizontal.xml,这就是我们今天的主角了: 1. <layer-list xmlns:Android="http://schemas.Android.com/apk/res/Android"> 2. 3. <item Android:id="@Android:id/background"> 4. <shape> 5. <corners Android:radius="5dip" /> 6. <gradient 7. Android[/img] 注意看,四角还是有圆倒角的,貌似是系统自己加上去的,总之我的图片里面是没有做这个倒角处理的 二)纵向进度条 还是得从源码入手,看回progress_horizontal.xml 1. <item Android:id="@Android:id/progress"> 2. <clip> 3. <shape> 4. <corners Android:radius="5dip" /> 5. <gradient 6. Android[/img] 三)弧形bar 这个也许算不上是进度条,用的也不多,最多也就仪表盘用用,不然谁会把进度条整成圆弧的呢。好吧这个可不是改改源码就能搞定的,看代码 1. public class Arcs extends View { 2. private Paint mArcPaint; 3. private Paint mArcBGPaint; 4. 5. private RectF mOval; 6. private float mSweep = 0; 7. private int mSpeedMax = 200; 8. private int mThreshold = 100; 9. private int mIncSpeedValue = 0; 10. private int mCurrentSpeedValue = 0; 11. private float mCenterX; 12. private float mCenterY; 13. private float mSpeedArcWidth; 14. 15. private final float SPEED_VALUE_INC = 2; 16. 17. .......... 18. 19. } 首先是一堆成员变量,两个Paint用来画圆弧一个前景一个背景,一个RectF圆弧就画在上面,然后是一些控制参数比如sweep圆弧扫过的角度,xy坐标等等 1. mArcPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 2. mArcPaint.setStyle(Paint.Style.STROKE); 3. mArcPaint.setStrokeWidth(mSpeedArcWidth); 4. // mPaint.setStrokeCap(Paint.Cap.ROUND); 5. mArcPaint.setColor(0xff81ccd6); 6. BlurMaskFilter mBlur = new BlurMaskFilter(8, BlurMaskFilter.Blur.INNER); 7. mArcPaint.setMaskFilter(mBlur); 8. 9. mArcBGPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 10. mArcBGPaint.setStyle(Paint.Style.STROKE); 11. mArcBGPaint.setStrokeWidth(mSpeedArcWidth+8); 12. mArcBGPaint.setColor(0xff171717); 13. 14. BlurMaskFilter mBGBlur = new BlurMaskFilter(8, BlurMaskFilter.Blur.INNER); 15. mArcBGPaint.setMaskFilter(mBGBlur); 设置两个画笔,颜色,宽度,样式等等,BlurMaskFilter笔是边缘模糊效果,有几种,可以自己尝试 1. @Override 2. protected void onSizeChanged(int w, int h, int ow, int oh) { 3. super.onSizeChanged(w, h, ow, oh); 4. Log.i("onSizeChanged w", w+""); 5. Log.i("onSizeChanged h", h+""); 6. mCenterX = w * 0.5f; // remember the center of the screen 7. mCenterY = h - mSpeedArcWidth; 8. mOval = new RectF(mCenterX - mCenterY, mSpeedArcWidth, mCenterX + mCenterY, mCenterY * 2); 9. } 重写父类View的onSizeChanged,为的是自己根据布局中的大小做居中处理 1. @Override 2. protected void onDraw(Canvas canvas) { 3. drawSpeed(canvas); 4. calcSpeed(); 5. } 6. 7. private void drawSpeed(Canvas canvas) { 8. canvas.drawArc(mOval, 179, 181, false, mArcBGPaint); 9. 10. mSweep = (float) mIncSpeedValue / mSpeedMax * 180; 11. if (mIncSpeedValue > mThreshold) { 12. mArcPaint.setColor(0xFFFF0000); 13. } 14. else { 15. mArcPaint.setColor(0xFF00B0F0); 16. } 17. 18. canvas.drawArc(mOval, 180, mSweep, false, mArcPaint); 19. } 20. 21. private void calcSpeed() { 22. if (mIncSpeedValue < mCurrentSpeedValue) { 23. mIncSpeedValue += SPEED_VALUE_INC; 24. if (mIncSpeedValue > mCurrentSpeedValue) { 25. mIncSpeedValue = mCurrentSpeedValue; 26. } 27. invalidate(); 28. } 29. else if (mIncSpeedValue > mCurrentSpeedValue) { 30. mIncSpeedValue -= SPEED_VALUE_INC; 31. if (mIncSpeedValue < mCurrentSpeedValue) { 32. mIncSpeedValue = mCurrentSpeedValue; 33. } 34. invalidate(); 35. } 36. } 重写onDraw以便重绘canvas drawSpeed里面 通过计算mSweep = (float) mIncSpeedValue / mSpeedMax * 180; 然后canvas.drawArc(mOval, 180, mSweep, false, mArcPaint); 会根据mSweep的变化,画出相应长度的弧度来 根据与阈值的对比,还可以设定不同的 颜色: if (mIncSpeedValue > mThreshold) { mArcPaint.setColor(0xFFFF0000); } else { mArcPaint.setColor(0xFF00B0F0); } calcSpeed通过一个步进来控制增量或减量,以使弧度自然过渡,减少跳跃 ok,大功告成 ![]() | |
![]() | ![]() |