转载自:http://daimajishu.iteye.com/blog/1597988

废话不多说,先上效果图:

Android提供了很多基本的控件实现,但不是一个完整、强大的实现。
幸运的是,Android提供了自定义控件的实现,有了自定义控件,我们就可以再Android的基础控件上实现我们想要的功能或者自定义的外观。
以ProgressBar为例,对于可调节的进度条似乎只有长条形的ProgressBar(圆形的都是不停转动的那种)
假如我们想要一个可调节进度的圆形进度条呢。。。
Ok,下面我们直接切入主题(关于自定义控件的相关实现细节就不多说了,还不太清楚的童鞋先找相关资料补习一下)

该自定义控件的实现思路是继承自View,然后重写onDraw

先看看该类有哪些成员变量:

Java代码
  1. publicclassCircleProgressextendsView{
  2. privatestaticfinalintDEFAULT_MAX_VALUE=100;//默认进度条最大值
  3. privatestaticfinalintDEFAULT_PAINT_WIDTH=10;//默认画笔宽度
  4. privatestaticfinalintDEFAULT_PAINT_COLOR=0xffffcc00;//默认画笔颜色
  5. privatestaticfinalbooleanDEFAULT_FILL_MODE=true;//默认填充模式
  6. privatestaticfinalintDEFAULT_INSIDE_VALUE=0;//默认缩进距离
  7. privateCircleAttributemCircleAttribute;//圆形进度条基本属性
  8. privateintmMaxProgress;//进度条最大值
  9. privateintmMainCurProgress;//主进度条当前值
  10. privateintmSubCurProgress;//子进度条当前值
  11. privateCartoomEnginemCartoomEngine;//动画引擎
  12. privateDrawablemBackgroundPicture;//背景图

Java代码
  1. classCircleAttribute
  2. {
  3. publicRectFmRoundOval;//圆形所在矩形区域
  4. publicbooleanmBRoundPaintsFill;//是否填充以填充模式绘制圆形
  5. publicintmSidePaintInterval;//圆形向里缩进的距离
  6. publicintmPaintWidth;//圆形画笔宽度(填充模式下无视)
  7. publicintmPaintColor;//画笔颜色(即主进度条画笔颜色,子进度条画笔颜色为其半透明值)
  8. publicintmDrawPos;//绘制圆形的起点(默认为-90度即12点钟方向)
  9. publicPaintmMainPaints;//主进度条画笔
  10. publicPaintmSubPaint;//子进度条画笔
  11. publicPaintmBottomPaint;//无背景图时绘制所用画笔

Java代码
  1. classCartoomEngine
  2. {
  3. publicHandlermHandler;
  4. publicbooleanmBCartoom;//是否正在作动画
  5. publicTimermTimer;//用于作动画的TIMER
  6. publicMyTimerTaskmTimerTask;//动画任务
  7. publicintmSaveMax;//在作动画时会临时改变MAX值,该变量用于保存值以便恢复
  8. publicintmTimerInterval;//定时器触发间隔时间(ms)
  9. publicfloatmCurFloatProcess;//作动画时当前进度值

下面看看onDraw的代码片段:

Java代码
  1. publicvoidonDraw(Canvascanvas){
  2. //TODOAuto-generatedmethodstub
  3. super.onDraw(canvas);
  4. if(mBackgroundPicture==null)//没背景图的话就绘制底色
  5. {
  6. canvas.drawArc(mCircleAttribute.mRoundOval,0,360,mCircleAttribute.mBRoundPaintsFill,mCircleAttribute.mBottomPaint);
  7. }
  8. floatsubRate=(float)mSubCurProgress/mMaxProgress;
  9. floatsubSweep=360*subRate;
  10. canvas.drawArc(mCircleAttribute.mRoundOval,mCircleAttribute.mDrawPos,subSweep,mCircleAttribute.mBRoundPaintsFill,mCircleAttribute.mSubPaint);
  11. floatrate=(float)mMainCurProgress/mMaxProgress;
  12. floatsweep=360*rate;
  13. canvas.drawArc(mCircleAttribute.mRoundOval,mCircleAttribute.mDrawPos,sweep,mCircleAttribute.mBRoundPaintsFill,mCircleAttribute.mMainPaints);
  14. }

canvas的drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint) 方法是关键
相关参数说明大家详看SDK文档


控件大小决定oval
画笔属性设置paint
useCenter表示是否填充
startAngle是绘制圆弧的起点,我们使用-90度,即12点钟方向
sweepAngle是从起点顺时针绘制覆盖的角度,意味着进度值为30%的话,就是 360 * 30%

设置进度的代码片段:

Java代码
  1. publicsynchronizedvoidsetMainProgress(intprogress)
  2. {
  3. mMainCurProgress=progress;
  4. if(mMainCurProgress<0)
  5. {
  6. mMainCurProgress=0;
  7. }
  8. if(mMainCurProgress>mMaxProgress)
  9. {
  10. mMainCurProgress=mMaxProgress;
  11. }
  12. invalidate();
  13. }

设置进度值之后触发重绘,计算sweepAngle的值,最后完成绘制效果,怎么样,是不是就对上了



该控件的自定义属性如下:

Java代码
  1. <?xmlversion="1.0"encoding="utf-8"?>
  2. lt;resources>
  3. <declare-styleablename="CircleProgressBar">
  4. <attrname="max"format="integer"/><!--进度条最大值-->
  5. <attrname="fill"format="boolean"/><!--是否填充圆形区域-->
  6. <attrname="Paint_Width"format="integer"/><!--画笔宽度,填充模式下无效,会被重置为0-->
  7. <attrname="Paint_Color"format="integer"/><!--画笔颜色-->
  8. <attrname="Inside_Interval"format="integer"/><!--圆形区域向里缩进的距离-->
  9. </declare-styleable>
  10. lt;/resources>

再贴上本例的布局文件:

Java代码
  1. <?xmlversion="1.0"encoding="utf-8"?>
  2. <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:roundProgress="http://schemas.android.com/apk/res/com.genius.progress"
  4. android:layout_width="fill_parent"
  5. android:layout_height="fill_parent"
  6. android:orientation="vertical"
  7. android:background="#ffffff">
  8. <LinearLayout
  9. android:layout_height="wrap_content"
  10. android:layout_width="match_parent"
  11. android:id="@+id/linearLayout1"
  12. android:orientation="horizontal"
  13. android:gravity="center_horizontal">
  14. <Button
  15. android:text="增加主进度条"
  16. android:id="@+id/buttonAddMainPro"
  17. android:layout_width="wrap_content"
  18. android:layout_height="wrap_content"
  19. android:layout_weight="1">
  20. </Button>
  21. <Button
  22. android:text="增加子进度条"
  23. android:id="@+id/buttonAddSubPro"
  24. android:layout_width="wrap_content"
  25. android:layout_height="wrap_content"
  26. android:layout_weight="1">
  27. </Button>
  28. <ImageButton
  29. android:id="@+id/buttonImage"
  30. android:layout_width="wrap_content"
  31. android:layout_height="wrap_content"
  32. android:src="@drawable/background2"
  33. android:layout_weight="1"/>
  34. </LinearLayout>
  35. <LinearLayout
  36. android:layout_height="wrap_content"
  37. android:layout_width="match_parent"
  38. android:id="@+id/linearLayout2"
  39. android:orientation="horizontal"
  40. android:background="#ff0000"
  41. android:gravity="center_horizontal">
  42. <com.genius.circle.CircleProgress
  43. android:id="@+id/roundBar1"
  44. android:layout_width="wrap_content"
  45. android:layout_height="wrap_content"
  46. android:background="@drawable/background1"
  47. roundProgress:max="100"
  48. roundProgress:fill="false"
  49. roundProgress:Inside_Interval="5"
  50. roundProgress:Paint_Width="4"
  51. roundProgress:Paint_Color="0xff0000ff"
  52. />
  53. <com.genius.circle.CircleProgress
  54. android:id="@+id/roundBar2"
  55. android:layout_width="wrap_content"
  56. android:layout_height="wrap_content"
  57. android:background="@drawable/background3"
  58. roundProgress:max="100"
  59. roundProgress:Inside_Interval="8"
  60. roundProgress:fill="true"
  61. roundProgress:Paint_Width="4"
  62. roundProgress:Paint_Color="0xffaa5500"
  63. />
  64. <com.genius.circle.CircleProgress
  65. android:id="@+id/roundBar3"
  66. android:layout_width="96dp"
  67. android:layout_height="96dp"
  68. roundProgress:max="100"
  69. roundProgress:fill="false"
  70. roundProgress:Paint_Width="40"
  71. roundProgress:Inside_Interval="20"
  72. />
  73. </LinearLayout>
  74. <LinearLayout
  75. android:layout_height="wrap_content"
  76. android:layout_width="match_parent"
  77. android:id="@+id/linearLayout3"
  78. android:orientation="horizontal"
  79. android:gravity="center_horizontal|center_vertical"
  80. android:background="#00ff00">
  81. <Button
  82. android:text="启动动画"
  83. android:id="@+id/buttonStart"
  84. android:layout_width="100dip"
  85. android:layout_height="wrap_content">
  86. </Button>
  87. <com.genius.circle.CircleProgress
  88. android:id="@+id/roundBar4"
  89. android:layout_width="wrap_content"
  90. android:layout_height="wrap_content"
  91. android:background="@drawable/background1"
  92. roundProgress:Inside_Interval="6"
  93. roundProgress:Paint_Color="0xff0000ff"
  94. />
  95. <Button
  96. android:text="停止动画"
  97. android:id="@+id/buttonStop"
  98. android:layout_width="100dip"
  99. android:layout_height="wrap_content">
  100. </Button>
  101. </LinearLayout>
  102. </LinearLayout>

大家比对下效果图就明白了


此外该控件中有两个接口是作动画相关的
public synchronized void startCartoom(int time)
public synchronized void stopCartoom()

比如你想播放一个10秒的声音片段,同时用进度条来表示播放进度,那么直接调用 startCartoom(10)来开启动画即可

其他的似乎没啥好说的了,源码工程里的注释也写很清楚了,有兴趣的童鞋下下来看看就明白了
附属工程链接:

http://download.csdn.net/detail/geniuseoe2012/4387677

喜欢就顶一下,你们的支持是窝的动力。

更多相关文章

  1. Android控件编辑时键盘弹起与关闭处理
  2. 布局中文件中【控件间距参数详解以及单位选择】
  3. android launcher 分析
  4. Android中shape定义控件的使用
  5. Android的ListView控件滚动时背景问题
  6. android控件的对齐方式
  7. 自定义控件之View原理与使用
  8. Robot Framework如何对Android的控件定位
  9. Android开发者e周报 第1期

随机推荐

  1. 在jQuery Mobile中做$(document).ready的正
  2. jQuery使用微调器加载整个HTML页面
  3. 通过调用返回参数的本地函数来构建Ajax D
  4. Zepto自定义选择器与Jq存在差异
  5. EasyUI动态展示用户信息
  6. js 中输入验证
  7. jquery兼容性问题
  8. JQuery和Struts实现Ajax文件上传
  9. 用JQuery写的一个简单的验证码功能
  10. 使用jQuery确认对话框防止上的表单回发