Android自己定义控件:进度条的四种实现方式

前三种实现方式代码出自:

http://stormzhang.com/openandroid/2013/11/15/android-custom-loading/

(源代码下载)http://download.csdn.net/detail/chaoyu168/9616035

近期一直在学习自己定义控件,搜了很多大牛们Blog里分享的小教程。也上GitHub找了一些类似的控件进行学习。发现读起来都不太好懂,就想写这么一篇东西作为学习笔记吧。

一、控件介绍:

进度条在App中非经常见,比例如以下载进度、载入图片、打开文章、打开网页等等……都须要这么一个效果让用户知道我们的App正在读取。以构造良好的交互。假设没有这样一个效果的话。用户没法知道东西有没有下载好、图片载入了没有、文章打开了没……会让用户非常不爽。基于这种情景我们的UI设计师们创造了这样一个控件。

二、这篇文章会涉及的知识点:

跟我一样刚入门的Android菜鸟们。我推荐大家先了解一下这些知识点再往下看。

这些知识点我也会推荐一些博客给大家看看。更推荐大家看文档里的解释,当然大牛们能够直接无视……

1、ClipDrawable类:可以对一个drawable类进行剪切操作(即仅仅显示某一部分的区域,还有一部分隐藏),显示多大的区域由level控制(level取值是0~10000)

【博客:http://blog.csdn.net/lonelyroamer/article/details/8244777】、没文档的能够在这看【http://www.apihome.cn/api/android/ClipDrawable.html】

2、自己定义View:guolin大神的深入学习View四部曲

Android
LayoutInflater原理分析,带你一步步深入了解View
——http://blog.csdn.net/guolin_blog/article/details/12921889】

Android视图绘制流程全然解析。带你一步步深入了解View——http://blog.csdn.net/guolin_blog/article/details/16330267】

Android视图状态及重绘流程分析,带你一步步深入了解View——http://blog.csdn.net/guolin_blog/article/details/17045157】

Android自己定义View的实现方法,带你一步步深入了解View——http://blog.csdn.net/guolin_blog/article/details/17357967】

3、没看过我写的:Android自己定义控件——老版优酷三级菜单的话,也许须要看看这个:

【RotateAnimation具体解释——http://blog.csdn.net/u012403246/article/details/41415799】

三、Android上的实现方式:

(前三种方法比較简单,第四种方法是GitHub项目的解析,对前三种没兴趣能够直接跳到后边……)

1、效果图:

将进度条的变换过程分解为一帧一帧的图片,将这些一帧一帧的图片连起来构成一个动画。

经常使用于:手机阅读网页、逛社区时,载入图片、文章等不须要清楚知道载入进度,可是须要知道是否进行载入的情景。

这样的方法实现能够通过创建一个animation-list的XML文件,然后给系统API提供的ProgressBar的indeterminateDrawable属性就能够了。(这个属性应该是类似于设置一个动画吧……)

XML:

[html] view
plain
 copy

  1. <?

    xml version="1.0" encoding="utf-8"?>

  2. <animation-list xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:oneshot="false" >
  4. <item android:duration="150" >
  5. <clip
  6. android:clipOrientation="horizontal"
  7. android:drawable="@drawable/loading_01"
  8. android:gravity="left"/>
  9. </item>
  10. <item android:duration="150" >
  11. <clip
  12. android:clipOrientation="horizontal"
  13. android:drawable="@drawable/loading_02"
  14. android:gravity="left"/>
  15. </item>
  16. <item android:duration="150" >
  17. <clip
  18. android:clipOrientation="horizontal"
  19. android:drawable="@drawable/loading_03"
  20. android:gravity="left"/>
  21. </item>
  22. <item android:duration="150" >
  23. <clip
  24. android:clipOrientation="horizontal"
  25. android:drawable="@drawable/loading_04"
  26. android:gravity="left"/>
  27. </item>
  28. <item android:duration="150" >
  29. <clip
  30. android:clipOrientation="horizontal"
  31. android:drawable="@drawable/loading_05"
  32. android:gravity="left"/>
  33. </item>
  34. <item android:duration="150" >
  35. <clip
  36. android:clipOrientation="horizontal"
  37. android:drawable="@drawable/loading_06"
  38. android:gravity="left"/>
  39. </item>
  40. <item android:duration="150" >
  41. <clip
  42. android:clipOrientation="horizontal"
  43. android:drawable="@drawable/loading_07"
  44. android:gravity="left"/>
  45. </item>
  46. <item android:duration="150" >
  47. <clip
  48. android:clipOrientation="horizontal"
  49. android:drawable="@drawable/loading_08"
  50. android:gravity="left"/>
  51. </item>
  52. <item android:duration="150" >
  53. <clip
  54. android:clipOrientation="horizontal"
  55. android:drawable="@drawable/loading_09"
  56. android:gravity="left"/>
  57. </item>
  58. <item android:duration="150" >
  59. <clip
  60. android:clipOrientation="horizontal"
  61. android:drawable="@drawable/loading_10"
  62. android:gravity="left"/>
  63. </item>
  64. <item android:duration="150" >
  65. <clip
  66. android:clipOrientation="horizontal"
  67. android:drawable="@drawable/loading_11"
  68. android:gravity="left"/>
  69. </item>
  70. <item android:duration="150" >
  71. <clip
  72. android:clipOrientation="horizontal"
  73. android:drawable="@drawable/loading_12"
  74. android:gravity="left"/>
  75. </item>
  76. </animation-list>

[html] view
plain
 copy

  1. <ProgressBar
  2. android:layout_width="wrap_content"
  3. android:layout_height="wrap_content"
  4. android:indeterminateDrawable="@drawable/progressbar1"
  5. />

2、效果图:

在上一篇有关自己定义控件的博客里我们使用了一个RotateAnimation类来实现旋转效果 (http://blog.csdn.net/u012403246/article/details/41309161),事实上。我们在这里也能够把一张图片,通过旋转。达到我们要的效果。本质上和上一种方法没多大差别。

我们仅仅须要创建一个rotate的XML。对其属性进行一些简单的设置。然后增加我们要用的图片就能够了。

XML:

[html] view
plain
 copy

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <rotate xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:pivotX="50%"
  4. android:pivotY="50%"
  5. android:fromDegrees="0"
  6. android:toDegrees="360"
  7. android:interpolator="@android:anim/accelerate_decelerate_interpolator" >
  8. <bitmap
  9. android:antialias="true"
  10. android:filter="true"
  11. android:src="@drawable/loading_360"/>
  12. </rotate>

[html] view
plain
 copy

  1. <ProgressBar
  2. android:layout_width="wrap_content"
  3. android:layout_height="wrap_content"
  4. android:indeterminateDrawable="@drawable/progressbar2"/>

3、效果图:

我们能够弄两张照片。第一张是纯黑色的,然后把这张照片中心挖一个圆出来,圆区域弄成白色,挖出来的圆弄成第二张照片。我们最好还是叠加显示两张照片,刚開始把第二张全然“遮住”。随着载入进度的添加,我们降低遮住的区域把第二张照片慢慢的显示出来。

Android上刚好就有这么一个ClipDrawable类,可以实现剪裁的过程。

我们来看看怎么通过这种方式自己定义一个进度条控件。

代码:

[java] view
plain
 copy

  1. public class MyProgressBar extends FrameLayout{
  2. private boolean running;
  3. private int progress = 0;
  4. private static final int MAX_PROGRESS = 10000;
  5. private ClipDrawable clip;
  6. private Handler handler = new Handler(){
  7. @Override
  8. public void handleMessage(android.os.Message msg) {
  9. if(msg.what == 0x123)
  10. clip.setLevel(progress);
  11. }
  12. };
  13. public MyProgressBar(Context context){
  14. this(context,null,0);
  15. }
  16. public MyProgressBar(Context context,AttributeSet attrs){
  17. this(context,null,0);
  18. }
  19. public MyProgressBar(Context context, AttributeSet attrs, int defStyle) {
  20. super(context, attrs, defStyle);
  21. Init(context);
  22. }
  23. public void Init(Context context){
  24. View view = LayoutInflater.from(context).inflate(R.layout.view, null);
  25. ImageView iv = (ImageView)view.findViewById(R.id.progress_img);
  26. addView(view);
  27. clip = (ClipDrawable)iv.getDrawable();
  28. Thread thread = new Thread(new Runnable() {
  29. @Override
  30. public void run() {
  31. running = true;
  32. while(running){
  33. handler.sendEmptyMessage(0x123);
  34. if(progress == MAX_PROGRESS)
  35. progress = 0;
  36. progress += 100;
  37. try {
  38. Thread.sleep(18);
  39. } catch (InterruptedException e) {
  40. e.printStackTrace();
  41. }
  42. }
  43. }
  44. });
  45. thread.start();
  46. }
  47. public void stop(){
  48. progress = 0;
  49. running = false;
  50. }
  51. }

通过代码我们能够看到。逻辑很easy。关键就在于ClipDrawable的setLevel()方法,这个是设置剪裁效果的。

4、效果图:

实现一个View的子类——Progress Wheel类,实现进度条效果。

详细的内容我都写在了凝视上,假设不了解自己定义控件的知识。能够去阅读guolin博客里自己定义View四部曲的解说,讲的挺好的。

代码:

[java] view
plain
 copy

  1. public class ProgressWheel extends View {
  2. //绘制View用到的各种长、宽带大小
  3. private int layout_height = 0;
  4. private int layout_width = 0;
  5. private int fullRadius = 100;
  6. private int circleRadius = 80;
  7. private int barLength = 60;
  8. private int barWidth = 20;
  9. private int rimWidth = 20;
  10. private int textSize = 20;
  11. private float contourSize = 0;
  12. //与页边的间距
  13. private int paddingTop = 5;
  14. private int paddingBottom = 5;
  15. private int paddingLeft = 5;
  16. private int paddingRight = 5;
  17. //View要绘制的颜色
  18. private int barColor = 0xAA000000;
  19. private int contourColor = 0xAA000000;
  20. private int circleColor = 0x00000000;
  21. private int rimColor = 0xAADDDDDD;
  22. private int textColor = 0xFF000000;
  23. //绘制要用的画笔
  24. private Paint barPaint = new Paint();
  25. private Paint circlePaint = new Paint();
  26. private Paint rimPaint = new Paint();
  27. private Paint textPaint = new Paint();
  28. private Paint contourPaint = new Paint();
  29. //绘制要用的矩形
  30. @SuppressWarnings("unused")
  31. private RectF rectBounds = new RectF();
  32. private RectF circleBounds = new RectF();
  33. private RectF circleOuterContour = new RectF();
  34. private RectF circleInnerContour = new RectF();
  35. //动画
  36. //每次绘制要移动的像素数目
  37. private int spinSpeed = 2;
  38. //绘制过程的时间间隔
  39. private int delayMillis = 0;
  40. int progress = 0;
  41. boolean isSpinning = false;
  42. //其它
  43. private String text = "";
  44. private String[] splitText = {};
  45. /**
  46. * ProgressWheel的构造方法
  47. *
  48. * @param context
  49. * @param attrs
  50. */
  51. public ProgressWheel(Context context, AttributeSet attrs) {
  52. super(context, attrs);
  53. parseAttributes(context.obtainStyledAttributes(attrs,
  54. R.styleable.ProgressWheel));
  55. }
  56. //----------------------------------
  57. //初始化一些元素
  58. //----------------------------------
  59. /*
  60. * 调用这种方法时,使View绘制为方形
  61. * From: http://www.jayway.com/2012/12/12/creating-custom-android-views-part-4-measuring-and-how-to-force-a-view-to-be-square/
  62. *
  63. */
  64. @Override
  65. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  66. // 首先我们要调用超类的onMeasure借口
  67. // 原因是我们自己去实现一个方法获得长度、宽度太麻烦了
  68. // 使用超类的的方法很方便并且让复杂的细节可控
  69. super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  70. // 在这里我们不能使用getWidth()和getHeight()。
  71. // 由于这两个方法仅仅能在View的布局完毕后才干使用。而一个View的绘制过程是先绘制元素,再绘制Layout
  72. // 所以我们必须使用getMeasuredWidth()和getMeasuredHeight()
  73. int size = 0;
  74. int width = getMeasuredWidth();
  75. int height = getMeasuredHeight();
  76. int widthWithoutPadding = width - getPaddingLeft() - getPaddingRight();
  77. int heigthWithoutPadding = height - getPaddingTop() - getPaddingBottom();
  78. // 最后我们用一些简单的逻辑去计算View的大小并调用setMeasuredDimension()去设置View的大小
  79. // 在比較View的长宽前我们不考虑间距,但当我们设置View所须要绘制的面积时。我们要考虑它
  80. // 不考虑间距的View(View内的实际画面)此时就应该是方形的,可是因为间距的存在,终于View所占的面积可能不是方形的
  81. if (widthWithoutPadding > heigthWithoutPadding) {
  82. size = heigthWithoutPadding;
  83. } else {
  84. size = widthWithoutPadding;
  85. }
  86. // 假设你重写了onMeasure()方法。你必须调用setMeasuredDimension()方法
  87. // 这是你设置View大小的唯一途径
  88. // 假设你不调用setMeasuredDimension()方法,父控件会抛出异常。而且程序会崩溃
  89. // 假设我们使用了超类的onMeasure()方法,我们就不是那么须要setMeasuredDimension()方法
  90. // 然而,重写onMeasure()方法是为了改变既有的绘制流程。所以我们必须调用setMeasuredDimension()方法以达到我们的目的
  91. setMeasuredDimension(size + getPaddingLeft() + getPaddingRight(), size + getPaddingTop() + getPaddingBottom());
  92. }
  93. /**
  94. * 使用onSizeChanged方法取代onAttachedToWindow获得View的面积
  95. * 由于这种方法会在測量了MATCH_PARENT和WRAP_CONTENT后立即被调用
  96. * 使用获得的面积设置View
  97. */
  98. @Override
  99. protected void onSizeChanged(int w, int h, int oldw, int oldh) {
  100. super.onSizeChanged(w, h, oldw, oldh);
  101. // Share the dimensions
  102. layout_width = w;
  103. layout_height = h;
  104. setupBounds();
  105. setupPaints();
  106. invalidate();
  107. }
  108. /**
  109. * 设置我们想要绘制的progress wheel的颜色
  110. */
  111. private void setupPaints() {
  112. barPaint.setColor(barColor);
  113. barPaint.setAntiAlias(true);
  114. barPaint.setStyle(Style.STROKE);
  115. barPaint.setStrokeWidth(barWidth);
  116. rimPaint.setColor(rimColor);
  117. rimPaint.setAntiAlias(true);
  118. rimPaint.setStyle(Style.STROKE);
  119. rimPaint.setStrokeWidth(rimWidth);
  120. circlePaint.setColor(circleColor);
  121. circlePaint.setAntiAlias(true);
  122. circlePaint.setStyle(Style.FILL);
  123. textPaint.setColor(textColor);
  124. textPaint.setStyle(Style.FILL);
  125. textPaint.setAntiAlias(true);
  126. textPaint.setTextSize(textSize);
  127. contourPaint.setColor(contourColor);
  128. contourPaint.setAntiAlias(true);
  129. contourPaint.setStyle(Style.STROKE);
  130. contourPaint.setStrokeWidth(contourSize);
  131. }
  132. /**
  133. * 设置元素的边界
  134. */
  135. private void setupBounds() {
  136. // 为了保持宽度和长度的一致。我们要获得layout_width和layout_height中较小的一个,从而绘制一个圆
  137. int minValue = Math.min(layout_width, layout_height);
  138. // 计算在绘制过程中在x,y方向的偏移量
  139. int xOffset = layout_width - minValue;
  140. int yOffset = layout_height - minValue;
  141. // 间距加上偏移量
  142. paddingTop = this.getPaddingTop() + (yOffset / 2);
  143. paddingBottom = this.getPaddingBottom() + (yOffset / 2);
  144. paddingLeft = this.getPaddingLeft() + (xOffset / 2);
  145. paddingRight = this.getPaddingRight() + (xOffset / 2);
  146. int width = getWidth(); //this.getLayoutParams().width;
  147. int height = getHeight(); //this.getLayoutParams().height;
  148. rectBounds = new RectF(paddingLeft,
  149. paddingTop,
  150. width - paddingRight,
  151. height - paddingBottom);
  152. circleBounds = new RectF(paddingLeft + barWidth,
  153. paddingTop + barWidth,
  154. width - paddingRight - barWidth,
  155. height - paddingBottom - barWidth);
  156. circleInnerContour = new RectF(circleBounds.left + (rimWidth / 2.0f) + (contourSize / 2.0f), circleBounds.top + (rimWidth / 2.0f) + (contourSize / 2.0f), circleBounds.right - (rimWidth / 2.0f) - (contourSize / 2.0f), circleBounds.bottom - (rimWidth / 2.0f) - (contourSize / 2.0f));
  157. circleOuterContour = new RectF(circleBounds.left - (rimWidth / 2.0f) - (contourSize / 2.0f), circleBounds.top - (rimWidth / 2.0f) - (contourSize / 2.0f), circleBounds.right + (rimWidth / 2.0f) + (contourSize / 2.0f), circleBounds.bottom + (rimWidth / 2.0f) + (contourSize / 2.0f));
  158. fullRadius = (width - paddingRight - barWidth) / 2;
  159. circleRadius = (fullRadius - barWidth) + 1;
  160. }
  161. /**
  162. * 从XML中解析控件的属性
  163. *
  164. * @param a the attributes to parse
  165. */
  166. private void parseAttributes(TypedArray a) {
  167. barWidth = (int) a.getDimension(R.styleable.ProgressWheel_barWidth,
  168. barWidth);
  169. rimWidth = (int) a.getDimension(R.styleable.ProgressWheel_rimWidth,
  170. rimWidth);
  171. spinSpeed = (int) a.getDimension(R.styleable.ProgressWheel_spinSpeed,
  172. spinSpeed);
  173. delayMillis = a.getInteger(R.styleable.ProgressWheel_delayMillis,
  174. delayMillis);
  175. if (delayMillis < 0) {
  176. delayMillis = 0;
  177. }
  178. barColor = a.getColor(R.styleable.ProgressWheel_barColor, barColor);
  179. barLength = (int) a.getDimension(R.styleable.ProgressWheel_barLength,
  180. barLength);
  181. textSize = (int) a.getDimension(R.styleable.ProgressWheel_textSize,
  182. textSize);
  183. textColor = (int) a.getColor(R.styleable.ProgressWheel_textColor,
  184. textColor);
  185. //假设text是空的,就无视它
  186. if (a.hasValue(R.styleable.ProgressWheel_text)) {
  187. setText(a.getString(R.styleable.ProgressWheel_text));
  188. }
  189. rimColor = (int) a.getColor(R.styleable.ProgressWheel_rimColor,
  190. rimColor);
  191. circleColor = (int) a.getColor(R.styleable.ProgressWheel_circleColor,
  192. circleColor);
  193. contourColor = a.getColor(R.styleable.ProgressWheel_contourColor, contourColor);
  194. contourSize = a.getDimension(R.styleable.ProgressWheel_contourSize, contourSize);
  195. // 使用TypedArray获得控件属性时必需要注意:使用结束后必须回收TypedArray的对象
  196. a.recycle();
  197. }
  198. //----------------------------------
  199. //动画
  200. //----------------------------------
  201. protected void onDraw(Canvas canvas) {
  202. super.onDraw(canvas);
  203. //绘制内圆
  204. canvas.drawArc(circleBounds, 360, 360, false, circlePaint);
  205. //绘制边界
  206. canvas.drawArc(circleBounds, 360, 360, false, rimPaint);
  207. canvas.drawArc(circleOuterContour, 360, 360, false, contourPaint);
  208. canvas.drawArc(circleInnerContour, 360, 360, false, contourPaint);
  209. //绘制条纹
  210. if (isSpinning) {
  211. canvas.drawArc(circleBounds, progress - 90, barLength, false,
  212. barPaint);
  213. } else {
  214. canvas.drawArc(circleBounds, -90, progress, false, barPaint);
  215. }
  216. //绘制我们想要设置的文字 (并让它显示在圆水平和垂直方向的中心处)
  217. float textHeight = textPaint.descent() - textPaint.ascent();
  218. float verticalTextOffset = (textHeight / 2) - textPaint.descent();
  219. for (String s : splitText) {
  220. float horizontalTextOffset = textPaint.measureText(s) / 2;
  221. canvas.drawText(s, this.getWidth() / 2 - horizontalTextOffset,
  222. this.getHeight() / 2 + verticalTextOffset, textPaint);
  223. }
  224. if (isSpinning) {
  225. scheduleRedraw();
  226. }
  227. }
  228. private void scheduleRedraw() {
  229. progress += spinSpeed;
  230. if (progress > 360) {
  231. progress = 0;
  232. }
  233. postInvalidateDelayed(delayMillis);
  234. }
  235. /**
  236. *   推断wheel是否在旋转
  237. */
  238. public boolean isSpinning() {
  239. if(isSpinning){
  240. return true;
  241. } else {
  242. return false;
  243. }
  244. }
  245. /**
  246. * 重设进度条的值
  247. */
  248. public void resetCount() {
  249. progress = 0;
  250. setText("0%");
  251. invalidate();
  252. }
  253. /**
  254. * 停止进度条的旋转
  255. */
  256. public void stopSpinning() {
  257. isSpinning = false;
  258. progress = 0;
  259. postInvalidate();
  260. }
  261. /**
  262. * 让进度条开启旋转模式
  263. */
  264. public void spin() {
  265. isSpinning = true;
  266. postInvalidate();
  267. }
  268. /**
  269. * 让进度条每次添加1(最大值为360)
  270. */
  271. public void incrementProgress() {
  272. isSpinning = false;
  273. progress++;
  274. if (progress > 360)
  275. progress = 0;
  276. setText(Math.round(((float) progress / 360) * 100) + "%");
  277. postInvalidate();
  278. }
  279. /**
  280. * 设置进度条为一个确切的数值
  281. */
  282. public void setProgress(int i) {
  283. isSpinning = false;
  284. progress = i;
  285. postInvalidate();
  286. }
  287. //----------------------------------
  288. //get和set方法
  289. //----------------------------------
  290. /**
  291. * 设置progress bar的文字并不须要刷新View
  292. *
  293. * @param text the text to show (‘\n‘ constitutes a new line)
  294. */
  295. public void setText(String text) {
  296. this.text = text;
  297. splitText = this.text.split("\n");
  298. }
  299. public int getCircleRadius() {
  300. return circleRadius;
  301. }
  302. public void setCircleRadius(int circleRadius) {
  303. this.circleRadius = circleRadius;
  304. }
  305. public int getBarLength() {
  306. return barLength;
  307. }
  308. public void setBarLength(int barLength) {
  309. this.barLength = barLength;
  310. }
  311. public int getBarWidth() {
  312. return barWidth;
  313. }
  314. public void setBarWidth(int barWidth) {
  315. this.barWidth = barWidth;
  316. if ( this.barPaint != null ) {
  317. this.barPaint.setStrokeWidth( this.barWidth );
  318. }
  319. }
  320. public int getTextSize() {
  321. return textSize;
  322. }
  323. public void setTextSize(int textSize) {
  324. this.textSize = textSize;
  325. if ( this.textPaint != null ) {
  326. this.textPaint.setTextSize( this.textSize );
  327. }
  328. }
  329. public int getPaddingTop() {
  330. return paddingTop;
  331. }
  332. public void setPaddingTop(int paddingTop) {
  333. this.paddingTop = paddingTop;
  334. }
  335. public int getPaddingBottom() {
  336. return paddingBottom;
  337. }
  338. public void setPaddingBottom(int paddingBottom) {
  339. this.paddingBottom = paddingBottom;
  340. }
  341. public int getPaddingLeft() {
  342. return paddingLeft;
  343. }
  344. public void setPaddingLeft(int paddingLeft) {
  345. this.paddingLeft = paddingLeft;
  346. }
  347. public int getPaddingRight() {
  348. return paddingRight;
  349. }
  350. public void setPaddingRight(int paddingRight) {
  351. this.paddingRight = paddingRight;
  352. }
  353. public int getBarColor() {
  354. return barColor;
  355. }
  356. public void setBarColor(int barColor) {
  357. this.barColor = barColor;
  358. if ( this.barPaint != null ) {
  359. this.barPaint.setColor( this.barColor );
  360. }
  361. }
  362. public int getCircleColor() {
  363. return circleColor;
  364. }
  365. public void setCircleColor(int circleColor) {
  366. this.circleColor = circleColor;
  367. if ( this.circlePaint != null ) {
  368. this.circlePaint.setColor( this.circleColor);
  369. }
  370. }
  371. public int getRimColor() {
  372. return rimColor;
  373. }
  374. public void setRimColor(int rimColor) {
  375. this.rimColor = rimColor;
  376. if ( this.rimPaint != null ) {
  377. this.rimPaint.setColor( this.rimColor );
  378. }
  379. }
  380. public Shader getRimShader() {
  381. return rimPaint.getShader();
  382. }
  383. public void setRimShader(Shader shader) {
  384. this.rimPaint.setShader(shader);
  385. }
  386. public int getTextColor() {
  387. return textColor;
  388. }
  389. public void setTextColor(int textColor) {
  390. this.textColor = textColor;
  391. if ( this.textPaint != null ) {
  392. this.textPaint.setColor( this.textColor );
  393. }
  394. }
  395. public int getSpinSpeed() {
  396. return spinSpeed;
  397. }
  398. public void setSpinSpeed(int spinSpeed) {
  399. this.spinSpeed = spinSpeed;
  400. }
  401. public int getRimWidth() {
  402. return rimWidth;
  403. }
  404. public void setRimWidth(int rimWidth) {
  405. this.rimWidth = rimWidth;
  406. if ( this.rimPaint != null ) {
  407. this.rimPaint.setStrokeWidth( this.rimWidth );
  408. }
  409. }
  410. public int getDelayMillis() {
  411. return delayMillis;
  412. }
  413. public void setDelayMillis(int delayMillis) {
  414. this.delayMillis = delayMillis;
  415. }
  416. public int getContourColor() {
  417. return contourColor;
  418. }
  419. public void setContourColor(int contourColor) {
  420. this.contourColor = contourColor;
  421. if ( contourPaint != null ) {
  422. this.contourPaint.setColor( this.contourColor );
  423. }
  424. }
  425. public float getContourSize() {
  426. return this.contourSize;
  427. }
  428. public void setContourSize(float contourSize) {
  429. this.contourSize = contourSize;
  430. if ( contourPaint != null ) {
  431. this.contourPaint.setStrokeWidth( this.contourSize );
  432. }
  433. }
  434. }
时间: 2024-10-03 13:20:02

Android自己定义控件:进度条的四种实现方式的相关文章

Android开发之基本控件和详解四种布局方式

Android中的控件的使用方式和iOS中控件的使用方式基本相同,都是事件驱动.给控件添加事件也有接口回调和委托代理的方式.今天这篇博客就总结一下Android中常用的基本控件以及布局方式.说到布局方式Android和iOS还是区别挺大的,在iOS中有Frame绝对布局和AutoLayout相对布局.而在Android中的布局方式就比较丰富了,今天博客中会介绍四种常用的布局方式.先总结一下控件,然后再搞一搞基本方式,开发环境还是用的Mac下的Android Studio.开始今天的正题, 虽然A

Android自定义控件:进度条的四种实现方式

前三种实现方式代码出自: http://stormzhang.com/openandroid/2013/11/15/android-custom-loading/ (源码在最后) 最近一直在学习自定义控件,搜了许多大牛们Blog里分享的小教程,也上GitHub找了一些类似的控件进行学习.发现读起来都不太好懂,就想写这么一篇东西作为学习笔记吧. 一.控件介绍: 进度条在App中非常常见,例如下载进度.加载图片.打开文章.打开网页等等--都需要这么一个效果让用户知道我们的App正在读取,以构造良好的

Android自定义控件:进度条的四种实现方式(Progress Wheel的解析)(源码 + Demo)

Progress Wheel为GitHub热门项目,作者是:Todd-Davies,项目地址: https://github.com/Todd-Davies/ProgressWheel 前三种实现方式代码出自: http://stormzhang.com/openandroid/2013/11/15/android-custom-loading/ (源码在最后) 最近一直在学习自定义控件,搜了许多大牛们Blog里分享的小教程,也上GitHub找了一些类似的控件进行学习.发现读起来都不太好懂,就想

Android自己定义控件皮肤

Android自己定义控件皮肤 对于Android的自带控件,其外观仅仅能说中规中矩,而我们平时所示Android应用中,一个简单的button都做得十分美观.甚至于很多button在按下时的外观都有一定变化,用户体验十分好. 这当中,就涉及到了Android自己定义控件属性的操作方法,下面操作以实现自己定义button皮肤为例. 1. 我们要自己定义将要实现的外观状态.能够是图片或者是自己定义的xml,这是我们直接自己定义不同状态的颜色xml,在values文件夹下新建colors.xml,代

android 自己定义控件属性(TypedArray以及attrs解释)

近期在捣鼓android 自己定义控件属性,学到了TypedArray以及attrs.在这当中看了一篇大神博客Android 深入理解Android中的自己定义属性.我就更加深入学习力一番.我就沿着这个学习,讲一下流程吧,兴许一篇还有应用. 1.attrs文件编写 <?xml version="1.0" encoding="utf-8"?> <resources> <attr name="titleText" for

android 自己定义控件

Android自己定义View实现非常easy 继承View,重写构造函数.onDraw.(onMeasure)等函数. 假设自己定义的View须要有自己定义的属性.须要在values下建立attrs.xml. 在当中定义你的属性. 在使用到自己定义View的xml布局文件里须要增加xmlns:前缀="http://schemas.android.com/apk/res/你的应用所在的包路径". 在使用自己定义属性的时候.使用前缀:属性名,如my:textColor="#FF

Android自己定义控件而且使其能够在xml中自己定义属性

为什么要自己定义View android开发中自己定义View的优点是显而易见的.比方说以下的这个顶部导航,它被设计出如今应用的每一个界面,但每次的内容却不尽同样.我们不能在每一个layout资源中都配置一组同样的View吧?假设使用<include layou="@layout/xxx"/>标签,尽管攻克了布局文件的重用性,可是相关View的初始化设置还是没可以重用(集中),须要每次都採用view.findViewById(id)来初始化他们. 有了对"可重用性

Silverlight中Image控件Stretch属性的四种值比较

通过设置Image控件Stretch属性的值可以控制图片的显示形式: 包含的值:None.Fill.Uniform.UniformToFill 1 <Grid x:Name="LayoutRoot" Background="White" Height="489" Width="603"> 2 <Image Height="150" HorizontalAlignment="Lef

Image控件Stretch属性的四种值比较

None:图片直接加载到Image控件中,不进行拉伸,如果Image控件的大小是100X100 而图 Fill:图片会拉伸或缩小以适应Image控件 长宽比可能改变 Uniform:图片会拉伸到最佳大小(不一定充满整个Image控件)保持长宽比不变 UniformToFill:图片会在不改变长宽比的前提下拉伸,它会充满整个Image控件 但可能被裁减.   使用的图片是220X220 Image控件是200x150 通过上面的显示效果就可以一目了然啦 None:显示200x150 它从图片的顶点