Android自定义控件之自定义进度条
16lz
2021-01-25
自定义控件的几个步骤:
1.在attrs.xml文件声明自定义属性。
2.在此类中通过TypedArray拿到自定义属性的值。
3.根据这些值完成onMeasure,onLayout()和onDraw()函数。
> attrs.xml文件
<?xml version="1.0" encoding="utf-8"?>
直线进度条MyProgressBar
import android.content.Context;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Paint;import android.util.AttributeSet;import android.util.TypedValue;import android.widget.ProgressBar;import com.example.yang.crazydemo.R;/** * createtime:2019/8/12 * author:Yang * describe: */public class MyProgressBar extends ProgressBar { private static final int DEFAULT_TEXT_SIZE=10;//sp private static final int DEFAULT_TEXT_COLOR=0xFFFC00D1; private static final int DEFAULT_COLOR_UNREACH=0XFFD3D6DA; private static final int DEFAULT_COLOR_REACH=DEFAULT_TEXT_COLOR; private static final int DEFAULT_HEIGHT_REACH=2;//dp private static final int DEFAULT_HEIGHT_UNREACH=2;//dp private static final int DEFAULT_TEXT_OFFSET=10;//dp protected int mTextColor=DEFAULT_TEXT_COLOR; protected int mTextSize=Sptopx(DEFAULT_TEXT_SIZE); protected int mTextOffset=Dptopx(DEFAULT_TEXT_OFFSET); protected int mReachColor=DEFAULT_COLOR_REACH; protected int mUnReachColor=DEFAULT_COLOR_UNREACH; protected int mReachHeight=Dptopx(DEFAULT_HEIGHT_REACH); protected int mUnReachHeight=Dptopx(DEFAULT_HEIGHT_UNREACH); protected Paint mpaint=new Paint(); protected int mRealWidth; public MyProgressBar(Context context) { this(context,null); } public MyProgressBar(Context context,AttributeSet attrs) { this(context,attrs,0); } public MyProgressBar(Context context,AttributeSet attrs,int defStyle) { super(context,attrs,defStyle); ObtainStyleAttrs(attrs); } protected void ObtainStyleAttrs(AttributeSet attrs) { TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.MyProgressBar); mTextSize=(int) typedArray.getDimension(R.styleable.MyProgressBar_progress_text_size, mTextSize); mReachColor=typedArray.getColor(R.styleable.MyProgressBar_progress_reach, mReachColor); mUnReachColor=typedArray.getColor(R.styleable.MyProgressBar_progress_unreach,mUnReachColor); mTextColor=typedArray.getColor(R.styleable.MyProgressBar_progress_text_color,mTextColor ); mTextOffset= (int) typedArray.getDimension(R.styleable.MyProgressBar_progress_text_offset,mTextOffset); mUnReachHeight= (int) typedArray.getDimension(R.styleable.MyProgressBar_progress_unreach_height,mUnReachHeight); mReachHeight= (int) typedArray.getDimension(R.styleable.MyProgressBar_progress_reach_height,mReachHeight); typedArray.recycle(); mpaint.setTextSize(mTextSize); } @Override protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthVal=MeasureSpec.getSize(widthMeasureSpec); int height=MeasureHeight(heightMeasureSpec); setMeasuredDimension(widthVal, height); mRealWidth=getMeasuredWidth()-getPaddingLeft()-getPaddingRight(); } @Override protected synchronized void onDraw(Canvas canvas) { canvas.save(); canvas.translate(getPaddingLeft(), getHeight()/2); boolean NOneedUnreach=false; float radio=getProgress()*1.0f/getMax(); String text=getProgress()+"%"; float textWidth=mpaint.measureText(text); float ProgressX=radio*mRealWidth; if(ProgressX+textWidth>mRealWidth){ ProgressX=mRealWidth-textWidth; NOneedUnreach=true; } float EndX=ProgressX-mTextOffset/2; //绘制reach if(EndX>0){ mpaint.setColor(mReachColor); mpaint.setStrokeWidth(mReachHeight); canvas.drawLine(0, 0, EndX, 0, mpaint); } //绘制text mpaint.setColor(mTextColor); int y= (int) (-(mpaint.ascent()+mpaint.descent())/2); canvas.drawText(text, ProgressX, y,mpaint); //绘制Unreach if(!NOneedUnreach){ mpaint.setColor(mUnReachColor); float start=ProgressX+mTextOffset/2+textWidth; mpaint.setStrokeWidth(mUnReachHeight); canvas.drawLine(start, 0,mRealWidth, 0, mpaint); } canvas.restore(); } private int MeasureHeight(int heightMeasureSpec) { int result=0; int Mode=MeasureSpec.getMode(heightMeasureSpec); int Size=MeasureSpec.getSize(heightMeasureSpec); if(Mode==MeasureSpec.EXACTLY){ result=Size; }else{ int TextSize= (int) (mpaint.descent()-mpaint.ascent()); result=getPaddingTop()+getPaddingBottom()+Math.max(Math.max(mReachHeight, mUnReachHeight) , Math.abs(TextSize)); if(Mode==MeasureSpec.AT_MOST){ result=Math.min(result, Size); } } return result; } public int Dptopx(int dpval){ return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpval, getResources().getDisplayMetrics()); } public int Sptopx(int spval){ return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, spval, getResources().getDisplayMetrics()); }}
圆形进度条MyRoundProgressBar
import android.content.Context;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.RectF;import android.util.AttributeSet;import com.example.yang.crazydemo.R;/** * createtime:2019/8/13 * author:Yang * describe:圆形的进度条 */public class MyRoundProgressBar extends MyProgressBar { private int mRadius=Dptopx(30); private int mMaxPaintWidth; public MyRoundProgressBar(Context context) { this(context,null); } public MyRoundProgressBar(Context context, AttributeSet attrs) { this(context, attrs, 0); } public MyRoundProgressBar(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mReachHeight= (int) (2.5f*mUnReachHeight); TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyRoundProgressBar); mRadius= (int) typedArray.getDimension(R.styleable.MyRoundProgressBar_progress_radius, mRadius); typedArray.recycle(); mpaint.setAntiAlias(true); mpaint.setDither(true); mpaint.setStyle(Paint.Style.STROKE); mpaint.setStrokeCap(Paint.Cap.ROUND); } @Override protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { mMaxPaintWidth=Math.max(mReachHeight, mUnReachHeight); int expect=2*mRadius+mMaxPaintWidth+getPaddingLeft()+getPaddingRight(); int height=resolveSize(expect, heightMeasureSpec); int width=resolveSize(expect,widthMeasureSpec); int realWidth=Math.min(height, width); mRadius=(realWidth-getPaddingRight()-getPaddingLeft()-mMaxPaintWidth)/2; setMeasuredDimension(realWidth, realWidth); } @Override protected synchronized void onDraw(Canvas canvas) { String text=getProgress()+"%"; int textwidth= (int) mpaint.measureText(text); int textheight=(int)(mpaint.descent()+mpaint.ascent())/2; canvas.save(); canvas.translate(getPaddingLeft()+mMaxPaintWidth/2, getPaddingTop()+mMaxPaintWidth/2); mpaint.setStyle(Paint.Style.STROKE); //绘制unReachbar mpaint.setColor(mUnReachColor); mpaint.setStrokeWidth(mUnReachHeight); canvas.drawCircle(mRadius, mRadius,mRadius , mpaint); //绘制Reachbar mpaint.setColor(mReachColor); mpaint.setStrokeWidth(mReachHeight); float sweepAngle=getProgress()*1.0f/getMax()*360; canvas.drawArc(new RectF(0,0,2*mRadius,2*mRadius) , 0, sweepAngle, false,mpaint ); //绘制Text mpaint.setStyle(Paint.Style.FILL); mpaint.setColor(mTextColor); canvas.drawText(text, mRadius-textwidth/2, mRadius-textheight, mpaint); canvas.restore(); }}
布局代码(view是包名)
<?xml version="1.0" encoding="utf-8"?>
Activity使用代码
import android.os.Handler;import android.os.Message;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import view.MyProgressBar;import view.MyRoundProgressBar;public class ProgressActivity extends AppCompatActivity {private MyProgressBar progressBarone;private MyRoundProgressBar myRoundProgressBar;private MyProgressBar progressBartwo;private MyRoundProgressBar myRoundProgressBartwo;private static final int UPDATA_MSG=0x111;private Handler handler=new Handler(){ @Override public void handleMessage(Message msg) { int ProgressX=progressBarone.getProgress(); int ProgressY=progressBartwo.getProgress(); progressBarone.setProgress(++ProgressX); myRoundProgressBar.setProgress(++ProgressX); progressBartwo.setProgress(--ProgressY); myRoundProgressBartwo.setProgress(--ProgressY); while(progressBarone.getProgress()>100){ removeMessages(UPDATA_MSG); } while (progressBartwo.getProgress()<0){ removeMessages(UPDATA_MSG); } handler.sendEmptyMessageDelayed(UPDATA_MSG, 100); }}; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_progress); progressBarone=findViewById(R.id.myprogress_one); myRoundProgressBar=findViewById(R.id.myprogress_three); progressBartwo=findViewById(R.id.myprogress_two); myRoundProgressBartwo=findViewById(R.id.myprogress_four); Message msg=new Message(); msg.what=1; handler.sendMessage(msg); }}
演示效果图
更多相关文章
- 没有一行代码,「2020 新冠肺炎记忆」这个项目却登上了 GitHub 中
- Android之Notification-android学习之旅(二)
- 如何单独编译Android源代码中的模块
- android中怎样获取IP地址
- Android学习笔记之获得屏幕属性DisplayMetrics
- Android图片代码换色,背景换色
- Android在listview添加checkbox实现原理与代码
- 正确的Flutter和Android交互代码
- android添加以太网ethernet方法 android框架添加