【Android自定义view系列】圆形百分比进度条
2017-02-20 19:48
555 查看
1.前言
本文由xygy8860原创,首发地址:http://blog.csdn.net/xygy8860/article/details/55101326,转载请注明。
在工作工程中,自己掌握的Android开发知识已经感觉到了瓶颈,Android初级知识没问题,写业务逻辑也没问题。但是作为一个Android开发工程师,并不能仅仅满足于现状,看到自身缺陷和瓶颈之后,需要对自身进行努力提高,以提升自身技能。
对于Android开发而言,自定义控件一直是Android开发进阶的一大方向,更何况,如今的APP已经不是简单的功能实现,用户对于APP的体验已经从功能实现转为用户体验,画面是否精美,转场动画是否别出心裁,UI是否美观大方?等等这些内容是必须考虑的。现如今同类APP越来越多,公司为了赢得客户,提高留存率,必然在体验和UI上下功夫。如果这时设计师设计出精美的UI,开发工程师说:I can't !,那么估计老板会说go out 了!
基于以上,开始了自定义View的学习。同时在学习过程中,记录下来,如果你也对自定义View有兴趣,我们也可以一同成长!
2.圆形百分比进度条UI分析
2.1为何会选择圆形百分比进度条?
现在下载进度条等已经高度自定义,传统的progressbar已经样式落后。在使用360手机助手等的过程中,圆形百分比进度条已经普遍而且非常精美,是常规下载组件的一部分。因此,圆形百分比进度条作为第一个学习对象。同时,在学习个过程中,完善一个自定义view的框架,可以很方便的集成各种自定义View。
在本文的学习过程中,学习参考了这篇文章http://blog.csdn.net/wingichoy/article/details/50334595,对于博主后面的自定义View文章,也准备系统的跟着学习下。在此感谢博主的文章,指出了自定义View学习的道路。
2.2 废话不说,上效果
录制的gif有点卡顿,不过在真机上还是很流畅的。
[b]2.3 自定义view知识储备[/b]
我们都知道,在自定义view的时候一般都要重写三个方法:onMeasure(),onLayout()和onDraw()。
[b]2.4 UI分析[/b]
在看到上面这个UI的时候,首先我们需要分析下UI的组成部分。任何高级UI都是有初级UI元素组成的,把一个高级UI拆解成一个个初级UI的组成部分,那么也就离我们实现它不远了。
从上面的gif图上我们可以看到,自定义圆形百分比进度条,含有三个元素:(1)一个大圆;(2)一个弧形色带;(3):百分比进度的文字。从上面的拆解我们可以发现,大圆好实现,文字也好实现,但是弧形色带怎么实现呢?
其实,经过分析我们也可以再次分解,将色带分解为:(1)一个圆弧;(2)一个中心小圆。这样实现是不是更加容易了呢?
最终,我们将UI拆解为四个部分:
3.圆形百分比进度条代码编写
3.1 继承View并实现构造函数
自定义view的第一步,必然是继承View或viewgroup,由于我们此文主要实现是控件,而不需要布局,同时我们是完全自绘控件,所以只需要继承View即可,同时实现构造函数。首先我们定义一个CircleProgressBar的自定义类,并实现构造函数。代码如下:
3.2 onMeasure
由于我们不涉及到改变控件在viewparent的位置问题,所以不需要重写onLayout()。所以我们重写的第一步是onMeasure()。
在重写onMeasure()的时候,需要了解一些其他知识。我们都知道,在xml中我们需要设置layout_height和layout_width属性,那么,控件在onMeasure()的时候,就需要用到这些属性。根据这篇博客http://blog.csdn.net/lmj623565791/article/details/24252901的解读:
3.3 onDraw
在控件测量完成之后,系统会调用onDraw()方法绘制控件,在此重写,达到绘制圆形百分比进度条的目的。onDraw()主要分四个方面,即上文提到的大圆、圆弧、小圆和文字,逐层进行绘制,顺序不可调换,不然会导致覆盖。
3.4 外部调用
布局方面写完之后,我们还需要向外界暴露一个借口,以控制进度条的显示和文字的改变。
3.5 成果
至此大功告成,我们只需要在布局中引用,即可验证我们的成果。布局中代码也很简单,和普通控件一样即可。
然后在代码中findViewById即可得到实例,根据下载进度,持续调用setPercent()方法就能达到动画效果。
3.6 扩展
在代码写完,功能实现之后,为了更好的扩展性,必须对控件的属性进行接口暴露,使用者能根据自己的意愿对控件进行适当的修改,以和应用的整体风格契合。因此,暴露以下方法:
4.源码
本文的源码已经上传github,地址:https://github.com/xygy8860/CustomView(求star),请各位自取,下载源码后可以按自己的风格自行修改
本文由xygy8860原创,首发地址:http://blog.csdn.net/xygy8860/article/details/55101326,转载请注明。
在工作工程中,自己掌握的Android开发知识已经感觉到了瓶颈,Android初级知识没问题,写业务逻辑也没问题。但是作为一个Android开发工程师,并不能仅仅满足于现状,看到自身缺陷和瓶颈之后,需要对自身进行努力提高,以提升自身技能。
对于Android开发而言,自定义控件一直是Android开发进阶的一大方向,更何况,如今的APP已经不是简单的功能实现,用户对于APP的体验已经从功能实现转为用户体验,画面是否精美,转场动画是否别出心裁,UI是否美观大方?等等这些内容是必须考虑的。现如今同类APP越来越多,公司为了赢得客户,提高留存率,必然在体验和UI上下功夫。如果这时设计师设计出精美的UI,开发工程师说:I can't !,那么估计老板会说go out 了!
基于以上,开始了自定义View的学习。同时在学习过程中,记录下来,如果你也对自定义View有兴趣,我们也可以一同成长!
2.圆形百分比进度条UI分析
2.1为何会选择圆形百分比进度条?
现在下载进度条等已经高度自定义,传统的progressbar已经样式落后。在使用360手机助手等的过程中,圆形百分比进度条已经普遍而且非常精美,是常规下载组件的一部分。因此,圆形百分比进度条作为第一个学习对象。同时,在学习个过程中,完善一个自定义view的框架,可以很方便的集成各种自定义View。
在本文的学习过程中,学习参考了这篇文章http://blog.csdn.net/wingichoy/article/details/50334595,对于博主后面的自定义View文章,也准备系统的跟着学习下。在此感谢博主的文章,指出了自定义View学习的道路。
2.2 废话不说,上效果
录制的gif有点卡顿,不过在真机上还是很流畅的。
[b]2.3 自定义view知识储备[/b]
我们都知道,在自定义view的时候一般都要重写三个方法:onMeasure(),onLayout()和onDraw()。
onDraw()必须有,用来绘制View图像 如果要改变View大小,需要重写onMeasure() 如果要改变View在父控件中的位置,需要重写onLayout()view还有其他的方法,也一并了解下,对于自定义view有时候非常有用。
>> onFinishInflate(): 这是一个回调方法,当应用从XML布局文件加载该组件并利用它来构建界面之后,该方法将会被回调。 >> onMeasure(int,int):调用该方法来检测View组件及它所包含的所有子组件的大小。 >> onLayout(boolean,int,int,int,int):当该组件需要分配其自组件的位置、大小时,该方法就会被回调。 >> onSizeChanged(int,int,int,int):当该组件的大小被改变时回调该方法。 >> onDraw(Canvas):当该组件需要绘制它的内容时回调该方法进行绘制。 >> onKeyDown(int,KeyEvent):当某个键被按下时触发该方法。 >> onKeyUp(int,KeyEvent):当松开某个按键时触发该方法。 >> onTrackballEvent(MotionEvent):当发生轨迹球事件时触发该方法 >> onTouchEvent(MotionEvent):当发生触摸屏事件时触发该方法 >> onWindowFocusChanged(boolean):当该组件得到、失去焦点时触发该方法。 >> onAttachedToWindow():当把组件放入某个窗口时触发该方法 >> onDetachedFrowWindow():当把组件从某个窗口上分离时触发该方法。 >> onWindowVisibilityChanged(int):当包含该组件的窗口的可见性发生改变时触发该方法。
[b]2.4 UI分析[/b]
在看到上面这个UI的时候,首先我们需要分析下UI的组成部分。任何高级UI都是有初级UI元素组成的,把一个高级UI拆解成一个个初级UI的组成部分,那么也就离我们实现它不远了。
从上面的gif图上我们可以看到,自定义圆形百分比进度条,含有三个元素:(1)一个大圆;(2)一个弧形色带;(3):百分比进度的文字。从上面的拆解我们可以发现,大圆好实现,文字也好实现,但是弧形色带怎么实现呢?
其实,经过分析我们也可以再次分解,将色带分解为:(1)一个圆弧;(2)一个中心小圆。这样实现是不是更加容易了呢?
最终,我们将UI拆解为四个部分:
(1)外层大圆; (2)中间圆弧; (3)内层小圆; (4)中心文字。其图层显示如下(图片来源于参考博客,感谢博主):
3.圆形百分比进度条代码编写
3.1 继承View并实现构造函数
自定义view的第一步,必然是继承View或viewgroup,由于我们此文主要实现是控件,而不需要布局,同时我们是完全自绘控件,所以只需要继承View即可,同时实现构造函数。首先我们定义一个CircleProgressBar的自定义类,并实现构造函数。代码如下:
// 将前面二个构造函数都指向第三个 public CircleProgressBar(Context context) { this(context, null); } // XML中使用此构造函数 public CircleProgressBar(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CircleProgressBar(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); // 默认值,色带宽度,文字大小等 mStripeWidth = PxUtils.dpToPx(30, context); mCenterTextSize = PxUtils.spToPx(20, context); mRadius = PxUtils.dpToPx(100, context); //绘制大圆画笔属性设置 bigCirclePaint = new Paint(); bigCirclePaint.setAntiAlias(true); // 抗锯齿 bigCirclePaint.setColor(mCircleColor); // 设置大圆颜色 //绘制小圆画笔属性设置 smallCirclePaint = new Paint(); smallCirclePaint.setAntiAlias(true); smallCirclePaint.setColor(mCircleColor); // 饼状图属性 rect = new RectF(); sectorPaint = new Paint(); sectorPaint.setColor(mAngleColor); sectorPaint.setAntiAlias(true); // 文字画笔属性 textPaint = new Paint(); textPaint.setColor(Color.WHITE); }
3.2 onMeasure
由于我们不涉及到改变控件在viewparent的位置问题,所以不需要重写onLayout()。所以我们重写的第一步是onMeasure()。
在重写onMeasure()的时候,需要了解一些其他知识。我们都知道,在xml中我们需要设置layout_height和layout_width属性,那么,控件在onMeasure()的时候,就需要用到这些属性。根据这篇博客http://blog.csdn.net/lmj623565791/article/details/24252901的解读:
当我们设置明确的宽度和高度时,系统帮我们测量的结果就是我们设置的结果,当我们设置为WRAP_CONTENT,或者MATCH_PARENT系统帮我们测量的结果就是MATCH_PARENT的长度。 所以,当设置了WRAP_CONTENT时,我们需要自己进行测量,即重写onMesure方法”:重写之前先了解MeasureSpec的specMode,一共三种类型: EXACTLY:一般是设置了明确的值或者是MATCH_PARENT AT_MOST:表示子布局限制在一个最大值内,一般为WARP_CONTENT UNSPECIFIED:表示子布局想要多大就多大,很少使用
MeasureSpec对象包含了测量的模式和大小。他是一个32位的int值,其中高两位为测量的模式,低30位是测量的大小。采用位运算和运行效率有关。所以可以从一个MeasureSpec对象分别获取模式和值 如: //获取模式 值为 EXACTLY AT_MOST UNSPECIFIED int specMode = MeasureSpec.getMode(measureSpec); //获取测量值 int specSize = MeasureSpec.getSize(measureSpec);了解了测量模式之后,我们就可以根据specMode 的值,来判断当前layout_height和layout_width的属性,从而计算出当前控件的实际宽高,此文中也即获得了大圆的半径。
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //获取测量模式 int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); //获取测量大小 int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); // match_parent if (widthMode == MeasureSpec.EXACTLY && heightMode == MeasureSpec.EXACTLY) { mRadius = widthSize / 2; x = widthSize / 2; y = heightSize / 2; mWidth = widthSize; mHeight = heightSize; } // warp_content // 如果是自适应,则取默认值 if (widthMode == MeasureSpec.AT_MOST && heightMode == MeasureSpec.AT_MOST) { mWidth = (int) (mRadius * 2); mHeight = (int) (mRadius * 2); x = mRadius; y = mRadius; } setMeasuredDimension(mWidth, mHeight); }
3.3 onDraw
在控件测量完成之后,系统会调用onDraw()方法绘制控件,在此重写,达到绘制圆形百分比进度条的目的。onDraw()主要分四个方面,即上文提到的大圆、圆弧、小圆和文字,逐层进行绘制,顺序不可调换,不然会导致覆盖。
@Override protected void onDraw(Canvas canvas) { mEndAngle = (int) (mCurPercent * 3.6); // 大圆 canvas.drawCircle(x, y, mRadius, bigCirclePaint); // 通过canvas画圆 //饼状图 rect.right = mWidth; rect.bottom = mHeight; //参数说明见知识补充 canvas.drawArc(rect, 270, mEndAngle, true, sectorPaint); // 小圆 canvas.drawCircle(x, y, mRadius - mStripeWidth, smallCirclePaint); //绘制文本 String text = mCurPercent + "%"; textPaint.setTextSize(mCenterTextSize); float textLength = textPaint.measureText(text); canvas.drawText(text, x - textLength / 2, y, textPaint); }
3.4 外部调用
布局方面写完之后,我们还需要向外界暴露一个借口,以控制进度条的显示和文字的改变。
// 外部设置百分比数 public void setPercent(int percent) { if (percent > 100 || percent < 0) { throw new IllegalArgumentException("percent must more than 0 and less than 100!"); } mCurPercent = percent; invalidate(); }
3.5 成果
至此大功告成,我们只需要在布局中引用,即可验证我们的成果。布局中代码也很简单,和普通控件一样即可。
<com.chenghui.customview.widget.CircleProgressBar android:id="@+id/circleView" android:layout_width="wrap_content" android:layout_height="wrap_content" />
然后在代码中findViewById即可得到实例,根据下载进度,持续调用setPercent()方法就能达到动画效果。
3.6 扩展
在代码写完,功能实现之后,为了更好的扩展性,必须对控件的属性进行接口暴露,使用者能根据自己的意愿对控件进行适当的修改,以和应用的整体风格契合。因此,暴露以下方法:
// 设置圆的颜色 public void setCircleColor(int mCircleColor) { this.mCircleColor = mCircleColor; smallCirclePaint.setColor(mCircleColor); bigCirclePaint.setColor(mCircleColor); // 此方法是为了使设置生效 invalidate(); } // 设置圆弧的颜色 public void setAngleColor(int mAngleColor) { this.mAngleColor = mAngleColor; sectorPaint.setColor(mAngleColor); invalidate(); } // 设置色带宽度 public void setStripeWidth(float mStripeWidth) { this.mStripeWidth = mStripeWidth; invalidate(); } // 设置字体颜色 public void setCenterTextColor(int color) { textPaint.setColor(color); invalidate(); } // 设置字体大小 public void setmCenterTextSize(float mCenterTextSize) { this.mCenterTextSize = mCenterTextSize; invalidate(); }
4.源码
本文的源码已经上传github,地址:https://github.com/xygy8860/CustomView(求star),请各位自取,下载源码后可以按自己的风格自行修改
相关文章推荐
- Android 自定义View修炼-自定义View-带百分比进度的圆形进度条(采用自定义属性)
- Android 自定义View 圆形百分比进度条
- Android自定义View实现带百分比圆形进度条
- android 圆形进度条 自定义view
- Android高手进阶之自定义View,自定义属性(带进度的圆形进度条)
- android自定义view(自定义带进度显示的圆形进度条)
- Android自定义控件之圆形进度条ImageView
- android开源系列:CircleImageView自定义圆形控件的使用
- Android 自定义View,自定义属性--自定义圆形进度条(整理)
- Android 高手进阶之自定义View,自定义属性(带进度的圆形进度条)
- android开源系列:CircleImageView自定义圆形控件的使用
- Android 高手进阶之自定义View,自定义属性(带进度的圆形进度条)
- Android 高手进阶之自定义View,自定义属性(带进度的圆形进度条)
- Android 高手进阶之自定义View,自定义属性(带进度的圆形进度条)
- Android 高手进阶之自定义View,自定义属性(带进度的圆形进度条)
- Android高手进阶之自定义View,自定义属性(带进度的圆形进度条)
- Android 高手进阶之自定义View,自定义属性(带进度的圆形进度条)
- Android 高手进阶之自定义View,自定义属性(带进度的圆形进度条)
- Android 高手进阶之自定义View,自定义属性(带进度的圆形进度条)
- 自定义View实现Android圆形进度条