赞
踩
自定义进度条继承View。自定义View主要重写OnMeasure()方法和onDraw()方法。onMeasure方法中主要计算控件的大小,onDraw方法绘制内容。
在计算控件大小的时候要注意测量模式。
先看下不同的测量模式下的打印结果
先设置match_parent 测量模式是EXACTLY
设置指定的大小测量模式还是EXACTLY
设置包裹内容测量模式变成了UNSPECIFIED
增加一个可滑动的父控件,测量模式变成了AT_MOST
不管是UNSPECIFIED还是AT_MOST最后MeasureSpec.getSize(widthMeasureSpec);获取的都是父控件的大小。
- package com.test;
-
- import android.content.Context;
- import android.content.res.TypedArray;
- import android.graphics.Bitmap;
- import android.graphics.BitmapFactory;
- import android.graphics.Canvas;
- import android.graphics.Paint;
- import android.graphics.PaintFlagsDrawFilter;
- import android.graphics.RectF;
- import android.util.AttributeSet;
- import android.util.Log;
- import android.view.MotionEvent;
- import android.view.View;
-
- import androidx.annotation.Nullable;
-
- public class MyProgress extends View {
-
- /**
- * 背景
- */
- private int mBackgroundColor; //背景颜色
- private RectF mBgRectF; //背景矩形
- private Paint mBgPaint; //bg画笔
-
- /**
- * 进度条
- */
- private int mProgress=0; //当前进度
- private int mProgressColor; //进度颜色
- private Paint mProgressPaint; //进度画笔
- private RectF mProgressRectF; //进度矩形
-
- /**
- * 滑块
- */
- private Paint mSliderPaint; //滑块画笔
- private RectF mSliderRectF; //滑块矩形
-
- /**
- * 进度条的宽高
- */
- private int mWidth;
- private int mHeight;
- private int mRadius;
-
- /**
- * 控件的宽高
- */
- private int mViewWidth;
- private int mViewHeight=0;
-
- /**
- * 滑块
- */
- private Bitmap circleBitmap;
- private int mBitmatWidth;
- private int mBitmatHeight;
-
- public MyProgress(Context context) {
- this(context,null);
- }
-
- public MyProgress(Context context, @Nullable AttributeSet attrs) {
- this(context, attrs,0);
- }
-
- public MyProgress(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- init(context,attrs);
- initPaint();
-
- }
-
- private void init(Context context,AttributeSet attrs) {
- TypedArray ta=context.obtainStyledAttributes(attrs,R.styleable.MyProgress);
- mBackgroundColor=ta.getColor(R.styleable.MyProgress_myProgressBgColor,context.getResources().getColor(R.color.colorLine));
- mProgressColor=ta.getColor(R.styleable.MyProgress_myProgressColor,context.getResources().getColor(R.color.text));
- mProgress=ta.getColor(R.styleable.MyProgress_myProgress,0);
- mHeight=ta.getDimensionPixelSize(R.styleable.MyProgress_myProgressHeight,10);
-
- circleBitmap= BitmapFactory.decodeResource(getResources(),ta.getResourceId(R.styleable.MyProgress_myProgressImg,R.mipmap.img_test));
- mRadius=ta.getDimensionPixelSize(R.styleable.MyProgress_myProgressRadius,10);
- ta.recycle();
-
- mBitmatWidth = circleBitmap.getWidth();
- mBitmatHeight = circleBitmap.getHeight();
- }
-
- private void initPaint() {
- mBgPaint = new Paint();
- mBgPaint.setAntiAlias(true);
- mBgPaint.setColor(mBackgroundColor);
- mBgPaint.setStyle(Paint.Style.FILL);
- mBgPaint.setStrokeCap(Paint.Cap.ROUND);
-
- mSliderPaint = new Paint();
- mSliderPaint.setAntiAlias(true);
- mSliderPaint.setColor(mProgressColor);
- mSliderPaint.setStyle(Paint.Style.FILL);
- mSliderPaint.setStrokeCap(Paint.Cap.ROUND);
-
- mProgressPaint = new Paint();
- mProgressPaint.setAntiAlias(true);
- mProgressPaint.setFilterBitmap(true);//paint抗锯齿(true);
- mProgressPaint.setColor(mProgressColor);
- mProgressPaint.setStyle(Paint.Style.FILL);
- mProgressPaint.setStrokeCap(Paint.Cap.ROUND);
-
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- //宽的测量模式
- int widthMode=MeasureSpec.getMode(widthMeasureSpec);
- //Extracts the size from the supplied measure specification.
- //翻译 从提供的度量规范中提取大小 获取指定大小没有就获取父控件的大小
- int width=MeasureSpec.getSize(widthMeasureSpec);
-
- int heightMode=MeasureSpec.getMode(heightMeasureSpec);
- int height=MeasureSpec.getSize(heightMeasureSpec);
-
- //EXACTLY == 1073741824
- //UNSPECIFIED == -2147483648
- //AT_MOST == 0
- Log.e("test","widthMode=="+widthMode);
- Log.e("test","width=="+width);
-
- int widthSize;
- int heightSize;
- if(widthMode==MeasureSpec.EXACTLY){ //已经确定具体大小 如设置match_parent或者设置具体值
- widthSize=width;
- }else{ //没有确定大小
- //为了方便随便定义一个大小
- widthSize=500;
- }
-
- if (heightMode == MeasureSpec.EXACTLY) {
- heightSize = height;
- } else {
- heightSize = mBitmatHeight; //没有定义高度就取滑块的高度
- }
-
- mViewWidth = widthSize;
- mViewHeight = heightSize;
-
- //进度条的宽度=控件宽-滑块宽
- mWidth = mViewWidth - mBitmatWidth;
-
- setMeasuredDimension(mViewWidth, mViewHeight);
- }
-
- private PaintFlagsDrawFilter mPaintFilter;
-
- private int left,top,right,bottom;
-
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
-
- if (mPaintFilter == null) {
- mPaintFilter = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
- //初始化背景的起始位置
- left=mBitmatWidth / 2;
- top=(mBitmatHeight - mHeight) / 2;
- right=(left + mWidth);
- bottom=(mBitmatHeight + mHeight)/2;
-
- }
- canvas.setDrawFilter(mPaintFilter);//canvas抗锯齿
- //画背景
- if (mBgRectF == null) {
- mBgRectF = new RectF(left, top, right, bottom);
- }
- canvas.drawRoundRect(mBgRectF, mRadius, mRadius, mBgPaint);
-
- //step2:画进度
- //起始位置和背景的起始位置一样
- if (mProgress == 0) {
- mProgressRectF = new RectF(left, top, left, top);
- } else {
- mProgressRectF = new RectF(left, top, (mViewWidth-mBitmatWidth)* mProgress/ 100+left, bottom);
- }
- canvas.drawRoundRect(mProgressRectF, mRadius, mRadius, mProgressPaint);
-
- //step3:画滑块
- // canvas.translate(0, -(circleBitmap.getHeight() - mHeight) / 2);
- if (mProgress == 0) {
- mSliderRectF = new RectF(0, 0, mBitmatWidth, mBitmatHeight);
- } else {
- mSliderRectF = new RectF((mViewWidth-mBitmatWidth)*mProgress/100 , 0, (mViewWidth-mBitmatWidth)* mProgress/ 100 + mBitmatWidth, mBitmatHeight);
- }
- canvas.drawBitmap(circleBitmap, null, mSliderRectF, mSliderPaint);
-
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
-
- if (event.getAction() == MotionEvent.ACTION_DOWN) {
- //按下,获取点击的位置
- float x = event.getX();
- float y = event.getY();
- if (x-mBitmatWidth/2-mWidth >= 0) {
- mProgress = 100;
- } else if (x <= mBitmatWidth / 2) {
- mProgress = 0;
- } else {
- mProgress = (int) ((x-mBitmatHeight/2) * 100 / mWidth);
- }
-
-
- } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
- //移动,获取移动后的位置
- float x = event.getX();
- float y = event.getY();
- //触摸在这个控件范围内
- if ((y > 0 && y < mBitmatHeight) && ((x>= mBitmatWidth/2) || (x<=mWidth + mBitmatWidth/2))) {
- if (x-mBitmatWidth/2-mWidth >= 0) {
- mProgress = 100;
- } else if (x <= mBitmatWidth / 2) {
- mProgress = 0;
- } else {
- mProgress = (int) ((x-mBitmatHeight/2) * 100 / mWidth);
- }
-
- }
- }
- invalidate();
- return true;
- }
- }
添加自定义属性
- <declare-styleable name="MyProgress">
- <!--背景颜色-->
- <attr name="myProgressBgColor" format="color|reference"/>
- <!--进度条颜色-->
- <attr name="myProgressColor" format="color|reference"/>
- <!--进度-->
- <attr name="myProgress" format="integer"/>
- <!--进度条的高-->
- <attr name="myProgressHeight" format="dimension|reference"/>
- <!--中间的图片-->
- <attr name="myProgressImg" format="reference"/>
- <!--圆角-->
- <attr name="myProgressRadius" format="dimension"/>
- </declare-styleable>
最后使用
- <com.test.MyProgress
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
最后博客写的少,没写好。不喜勿喷。
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。