Android 自定义View实现圆形进度条 深入理解onDraw和onMeasure及自定义属性
2017-06-23 17:45
831 查看
Android的View类是用户接口的基础构件,表示屏幕上的一块矩形区域,负责这个区域的绘制和事件处理。自定义View的过程主要包括重写onDraw及onMeasure方法 , 其中onMeasure方法的作用就是计算出自定义View的宽度和高度。这个计算的过程会参照父布局给出的大小(widthMeasureSpec和heightMeasureSpec),以及自己特点算出结果 ;onDraw则根据onMeasure测量后的宽高进行界面的绘制。onDraw主要用到两个类,Canvas和Paint。Canvas画布,相当于现实中画图用的纸或布;Paint画笔,相当于现实中的笔,基本方法有 drawLine 绘制直线 ,drawRect绘制矩形 , drawCirlce绘制圆形。
自定义圆形进度条效果如下
完整代码:
在values目录下新建attrs.xml文件 , 增加自定义属性
最后在布局文件中引入,设置自定义宽高和半径
自定义圆形进度条效果如下
完整代码:
package com.circleprogress; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RectF; import android.util.AttributeSet; import android.view.View; /** * Created by Administrator on 2017/6/22. */ public class CirlceView extends View { //定义第一支画笔,画背景的圆 private Paint mPaintBackCircle; //定义第二支画笔,画前景色的圆(进度条的环) private Paint mPaintFrontCircle; //定义绘制文字的画笔 private Paint mPaintText; //定义环的宽度 private float mStrokeWidth = 50 ; private float mhalfStrokeWidth = mStrokeWidth/2; //定义圆心坐标和半径 private float mX = 200 + mhalfStrokeWidth ; private float mY = 200 + mhalfStrokeWidth ; private float mRadius = 200 ; //定义矩形 private RectF mRectF ; //开始进度 private int mProgress = 0 ; //目标进度 private int mTargetProgress = 70 ; //最大进度 private int mMax = 100 ; //定义view的宽高 private int mWidth ; private int mHeight ; //默认半径 private static final int DEFAULT_RADIUS = 200 ; private static final int DEFAULT_STROKE_WIDTH = 50 ; public CirlceView(Context context) { this(context,null); } public CirlceView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CirlceView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); //获取自定义属性 if( attrs != null ){ TypedArray array = context.obtainStyledAttributes(attrs , R.styleable.CirlceView); mRadius = array.getDimensionPixelSize(R.styleable.CirlceView_radius , DEFAULT_RADIUS); mStrokeWidth = array.getDimensionPixelSize(R.styleable.CirlceView_stroke_width,DEFAULT_STROKE_WIDTH); array.recycle(); } init(); } private void initRect(){ if(mRectF == null ){ mRectF = new RectF(); int viewSize = (int) (mRadius*2); int left = (mWidth - viewSize)/2 ; int top = (mHeight - viewSize)/2 ; int right = left + viewSize ; int bottom = top + viewSize ; mRectF.set(left,top,right,bottom); } } //初始化画笔 private void init(){ mPaintBackCircle = new Paint(); //设置颜色 mPaintBackCircle.setColor(Color.WHITE); //设置防锯齿 mPaintBackCircle.setAntiAlias(true); //设置为空心 mPaintBackCircle.setStyle(Paint.Style.STROKE); mPaintBackCircle.setStrokeWidth(mStrokeWidth); mPaintFrontCircle = new Paint(); mPaintFrontCircle.setColor(0xFF66C796); mPaintFrontCircle.setAntiAlias(true); mPaintFrontCircle.setStyle(Paint.Style.STROKE); mPaintFrontCircle.setStrokeWidth(mStrokeWidth); mPaintText = new Paint(); mPaintText.setColor(0xFF66C796); mPaintText.setAntiAlias(true); mPaintText.setTextSize(50); //设置文字居中 mPaintText.setTextAlign(Paint.Align.CENTER); } @Override protected void onDraw(Canvas canvas) { initRect(); //获取进度百分比 float angle = mProgress/(float)mMax * 360 ; canvas.drawCircle(mWidth/2 , mHeight/2 , mRadius , mPaintBackCircle ); canvas.drawArc(mRectF , -90 , angle , false ,mPaintFrontCircle); canvas.drawText(mProgress+"%", mWidth/2 , mHeight/2 , mPaintText); if( mProgress < mTargetProgress) { //更新进度 mProgress += 2; //通知重新绘制 invalidate(); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); //测量宽高 mWidth = getRealSize(widthMeasureSpec); mHeight = getRealSize(heightMeasureSpec); //保存测量的宽高 setMeasuredDimension(mWidth,mHeight); } //测量View的真实尺寸 public int getRealSize( int measureSpec ){ int result = -1 ; int mode = MeasureSpec.getMode(measureSpec); int size = MeasureSpec.getSize(measureSpec); if( mode == MeasureSpec.AT_MOST || mode == MeasureSpec.UNSPECIFIED){ //自己计算 result = (int) (mRadius * 2 + mStrokeWidth); }else { result = size ; } return result; } }
在values目录下新建attrs.xml文件 , 增加自定义属性
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="CirlceView"> <attr name="radius" format="dimension"></attr> <attr name="stroke_width" format="dimension"></attr> <attr name="back_circle_color" format="color"></attr> <attr name="front_arc_color" format="color"></attr> <attr name="text_visibility" format="boolean"></attr> </declare-styleable> </resources>
最后在布局文件中引入,设置自定义宽高和半径
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.circleprogress.MainActivity"> <com.circleprogress.CirlceView android:layout_width="match_parent" android:layout_height="match_parent" app:radius="100dp" app:stroke_width="20dp"/> </RelativeLayout>
相关文章推荐
- 自定义View实现Android圆形进度条
- Android 自定义View onMeasure理解
- Android自定义View-绘制扇形实现圆形进度
- 【Android 界面效果15】Android UI 之一步步教你自定义控件(自定义属性、合理设计onMeasure、合理设计onDraw等)
- 自定义View实现Android圆形进度条,支持自定义显示的样式
- (总结篇)Android 牛不牛?决定于自定义View控件(一)——view绘制流程(onMeasure,onLayout,onDraw)
- Android UI 之一步步教你自定义控件(自定义属性、合理设计onMeasure、合理设计onDraw等)
- Android 自定义 view(四)—— onMeasure 方法理解
- Android自定义View(三、深入解析控件测量onMeasure)
- Android UI 之一步步教你自定义控件(自定义属性、合理设计onMeasure、合理设计onDraw等)
- android 自定义view中onMeasure()理解
- Android UI 之一步步教你自定义控件(自定义属性、合理设计onMeasure、合理设计onDraw等)
- Android学习自定义View(五)——自定义ViewGroup及其onMeasure()的理解
- Android 自定义View,自定义属性--自定义圆形进度条(整理)
- Android UI 之一步步教你自定义控件(自定义属性、合理设计onMeasure、合理设计onDraw等)
- Android UI 之一步步教你自定义控件(自定义属性、合理设计onMeasure、合理设计onDraw等)
- Android UI 之一步步教你自定义控件(自定义属性、合理设计onMeasure、合理设计onDraw等)
- 【view】android中onMeasure初看,深入理解布局之一!
- android中对自定义View的onMeasure()方法的理解
- Android:自定义View实现绚丽的圆形进度条