自定义实现圆形播放进度条(Android,飞一般的感觉)。
废话不多说,先上效果图:
Android提供了很多基本的控件实现,但不是一个完整、强大的实现。
幸运的是,Android提供了自定义控件的实现,有了自定义控件,我们就可以再Android的基础控件上实现我们想要的功能或者自定义的外观。
以ProgressBar为例,对于可调节的进度条似乎只有长条形的ProgressBar(圆形的都是不停转动的那种)
假如我们想要一个可调节进度的圆形进度条呢。。。
Ok,下面我们直接切入主题(关于自定义控件的相关实现细节就不多说了,还不太清楚的童鞋先找相关资料补习一下)
该自定义控件的实现思路是继承自View,然后重写onDraw
先看看该类有哪些成员变量:
1. public class CircleProgress extends
2.
3.
4. private static final int DEFAULT_MAX_VALUE = 100; // 默认进度条最大值
5. private static final int DEFAULT_PAINT_WIDTH = 10; // 默认画笔宽度
6. private static final int DEFAULT_PAINT_COLOR = 0xffffcc00; // 默认画笔颜色
7. private static final boolean DEFAULT_FILL_MODE = true; // 默认填充模式
8. private static final int DEFAULT_INSIDE_VALUE = 0; // 默认缩进距离
9.
10.
11. private CircleAttribute mCircleAttribute; // 圆形进度条基本属性
12.
13. private int mMaxProgress; // 进度条最大值
14. private int mMainCurProgress; // 主进度条当前值
15. private int mSubCurProgress; // 子进度条当前值
16.
17. private CartoomEngine mCartoomEngine; // 动画引擎
18.
19. private Drawable mBackgroundPicture; // 背景图
1. class
2. {
3. public RectF mRoundOval; // 圆形所在矩形区域
4. public boolean mBRoundPaintsFill; // 是否填充以填充模式绘制圆形
5. public int mSidePaintInterval; // 圆形向里缩进的距离
6. public int mPaintWidth; // 圆形画笔宽度(填充模式下无视)
7. public int mPaintColor; // 画笔颜色 (即主进度条画笔颜色,子进度条画笔颜色为其半透明值)
8. public int mDrawPos; // 绘制圆形的起点(默认为-90度即12点钟方向)
9.
10. public Paint mMainPaints; // 主进度条画笔
11. public Paint mSubPaint; // 子进度条画笔
12.
13. public Paint mBottomPaint; // 无背景图时绘制所用画笔
1. class
2. {
3. public
4. public boolean mBCartoom; // 是否正在作动画
5. public Timer mTimer; // 用于作动画的TIMER
6. public MyTimerTask mTimerTask; // 动画任务
7. public int mSaveMax; // 在作动画时会临时改变MAX值,该变量用于保存值以便恢复
8. public int mTimerInterval; // 定时器触发间隔时间(ms)
9. public float mCurFloatProcess; // 作动画时当前进度值
下面看看onDraw的代码片段:
1. public void
2. // TODO Auto-generated method stub
3. super.onDraw(canvas);
4.
5. if (mBackgroundPicture == null) // 没背景图的话就绘制底色
6. {
7. 0, 360, mCircleAttribute.mBRoundPaintsFill, mCircleAttribute.mBottomPaint);
8. }
9.
10.
11. float subRate = (float)mSubCurProgress / mMaxProgress;
12. float subSweep = 360
13. canvas.drawArc(mCircleAttribute.mRoundOval, mCircleAttribute.mDrawPos, subSweep, mCircleAttribute.mBRoundPaintsFill, mCircleAttribute.mSubPaint);
14.
15. float rate = (float)mMainCurProgress / mMaxProgress;
16. float sweep = 360
17. canvas.drawArc(mCircleAttribute.mRoundOval, mCircleAttribute.mDrawPos, sweep, mCircleAttribute.mBRoundPaintsFill, mCircleAttribute.mMainPaints);
18.
19.
20. }
canvas的drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint) 方法是关键
相关参数说明大家详看SDK文档 控件大小决定oval
画笔属性设置paint
useCenter表示是否填充
startAngle是绘制圆弧的起点,我们使用-90度,即12点钟方向
sweepAngle是从起点顺时针绘制覆盖的角度,意味着进度值为30%的话,就是 360 * 30% 设置进度的代码片段:
1. public synchronized void setMainProgress (int
2. {
3. mMainCurProgress = progress;
4. if (mMainCurProgress < 0)
5. {
6. 0;
7. }
8.
9. if
10. {
11. mMainCurProgress = mMaxProgress;
12. }
13.
14. invalidate();
15. }
设置进度值之后触发重绘,计算sweepAngle的值,最后完成绘制效果,怎么样,是不是就对上了
该控件的自定义属性如下:
1. <?xml version="1.0" encoding="utf-8"?>
2. lt;resources>
3.
4. "CircleProgressBar">
5. "max" format="integer"/> <!-- 进度条最大值 -->
6. "fill" format="boolean"/> <!-- 是否填充圆形区域 -->
7. "Paint_Width" format="integer"/> <!-- 画笔宽度,填充模式下无效,会被重置为0
8. "Paint_Color" format="integer"/> <!-- 画笔颜色 -->
9. "Inside_Interval" format="integer"/> <!-- 圆形区域向里缩进的距离 -->
10. </declare-styleable>
11.
12. lt;/resources>
再贴上本例的布局文件:
1. <?xml version="1.0" encoding="utf-8"?>
2. <LinearLayout xmlns:Android="http://schemas.android.com/apk/res/android"
3. "http://schemas.android.com/apk/res/com.genius.progress"
4. "fill_parent"
5. "fill_parent"
6. "vertical"
7. "#ffffff">
8.
9.
10. <LinearLayout
11. "wrap_content"
12. "match_parent"
13. "@+id/linearLayout1"
14. "horizontal"
15. "center_horizontal">
16.
17. <Button
18. "增加主进度条"
19. "@+id/buttonAddMainPro"
20. "wrap_content"
21. "wrap_content"
22. "1">
23. </Button>
24.
25.
26. <Button
27. "增加子进度条"
28. "@+id/buttonAddSubPro"
29. "wrap_content"
30. "wrap_content"
31. "1">
32. </Button>
33.
34. <ImageButton
35. "@+id/buttonImage"
36. "wrap_content"
37. "wrap_content"
38. "@drawable/background2"
39. "1"
40.
41. </LinearLayout>
42.
43.
44. <LinearLayout
45. "wrap_content"
46. "match_parent"
47. "@+id/linearLayout2"
48. "horizontal"
49. "#ff0000"
50. "center_horizontal">
51.
52.
53. <com.genius.circle.CircleProgress
54. "@+id/roundBar1"
55. "wrap_content"
56. "wrap_content"
57. "@drawable/background1"
58. "100"
59. "false"
60. "5"
61. "4"
62. "0xff0000ff"
63. />
64.
65.
66. <com.genius.circle.CircleProgress
67. "@+id/roundBar2"
68. "wrap_content"
69. "wrap_content"
70. "@drawable/background3"
71. "100"
72. "8"
73. "true"
74. "4"
75. "0xffaa5500"
76. />
77.
78.
79. <com.genius.circle.CircleProgress
80. "@+id/roundBar3"
81. "96dp"
82. "96dp"
83. "100"
84. "false"
85. "40"
86. "20"
87. />
88.
89. </LinearLayout>
90.
91.
92.
93.
94. <LinearLayout
95. "wrap_content"
96. "match_parent"
97. "@+id/linearLayout3"
98. "horizontal"
99. "center_horizontal|center_vertical"
100. "#00ff00">
101.
102.
103. <Button
104. "启动动画"
105. "@+id/buttonStart"
106. "100dip"
107. "wrap_content">
108. </Button>
109.
110.
111. <com.genius.circle.CircleProgress
112. "@+id/roundBar4"
113. "wrap_content"
114. "wrap_content"
115. "@drawable/background1"
116. "6"
117. "0xff0000ff"
118. />
119.
120. <Button
121. "停止动画"
122. "@+id/buttonStop"
123. "100dip"
124. "wrap_content">
125. </Button>
126.
127.
128. </LinearLayout>
129.
130.
131.
132. </LinearLayout>
大家比对下效果图就明白了
此外该控件中有两个接口是作动画相关的
public synchronized void startCartoom(int time)
public synchronized void stopCartoom()
比如你想播放一个10秒的声音片段,同时用进度条来表示播放进度,那么直接调用 startCartoom(10)来开启动画即可
其他的似乎没啥好说的了,源码工程里的注释也写很清楚了,有兴趣的童鞋下下来看看就明白了