android自定义一个带进度条的button
android自带的progressbar有时候显得不够灵活,不能满足项目的需求,所以研究了下带进度条的button如何来实现。
其实实现这个功能可以有两个方法,一个是通过布局,一个是通过写一个类来继承view自己通过画布来绘制。
第一个和第二个是通过画布来实现的,第三个是通过布局实现的。
先来说说第一种
其实就是两个矩形,一个是背景的矩形,一个是前面的进度条,也是一个矩形,再就是中间的文字。
核心代码:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//开始画背景图片
RectF oval = new RectF(0, 0, getWidth(), getHeight());
mPaint.setColor(mBackgroundColor);
canvas.drawRoundRect(oval, mCorner, mCorner, mPaint);
//开始画里面的进度条 坐标是 左上角 右下角
mPaint.setColor(mForcegroundColor);
if (mProgress < mCorner) {
oval = new RectF(0, mCorner - mProgress, (getWidth() * mProgress) / mMax, getHeight());
canvas.drawRoundRect(oval, mProgress, mProgress, mPaint);
} else {
oval = new RectF(0, 0, (getWidth() * mProgress) / mMax, getHeight());
canvas.drawRoundRect(oval, mCorner, mCorner, mPaint);
}
//开始画图片中间的文字
if (mText == null) {
return;
}
mPaint.setColor(mTextColor);
mPaint.setTextSize(mTextSize);
if (mProgress == 100) {
mText = "完成";
}
float[] widths = new float[mText.length() - 1];
mPaint.getTextWidths(mText, 0, mText.length() - 1, widths);
float textWidth = 0;
for (int i=0;i<widths.length;i++){
textWidth+=widths[i];
}
float textHeightinVer = getHeight()/2-mPaint.descent()+(mPaint.descent()-mPaint.ascent())/2;
canvas.drawText(mText, getWidth()/2-textWidth/widths.length,textHeightinVer,mPaint);
}
/**
*设置进度条的值
*/
public void setProgress(int progress) {
if (progress > mMax) {
mProgress = mMax;
}
this.mProgress = progress;
//强制刷新界面,绘制新的进度,此时会调用onDraw方法
postInvalidate();
}
中间的圆的进度条实现方式也一样,
核心代码:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mWidth = getWidth();
mHeight = getHeight();
mRadius = mWidth > mHeight ? mHeight / 2 : mWidth / 2;
float minRadius = mRadius * 3 / 4;
//画同心圆
//画一个外圆
mPaint.setColor(mBackgroundColor);
canvas.drawCircle(mWidth / 2, mHeight / 2, mRadius, mPaint);
//画进度条 从内圆的边缘到外圆的边缘
mPaint.setColor(mForcegroundColor);
// double degree = mProgress * mPerProgressDegree*Math.PI/Math.toDegrees(180);
float degree = mProgress * mPerProgressDegree;
// Log.i("ProgressRoundBar",mWidth / 2+"-->"+degree+"---->>"+minRadius+"--->>"+mRadius+"-->>"+minRadius * Math.cos(degree)+"-->"+fromX+"--"+fromY+":::"+toX+"--"+toY);
RectF oval = new RectF(0, 0, mRadius * 2, mRadius * 2);
canvas.drawArc(oval, 0, mProgress * 3.6f, true, mPaint);
//画一个内圆
mPaint.setColor(Color.argb(255, 255, 255, 255));
canvas.drawCircle(mWidth / 2, mHeight / 2, minRadius, mPaint);
//在yuan内圆的中间写上进度
mPaint.setColor(mForcegroundColor);
String progressText = null;
if (mProgress < 100) {
progressText = mProgress + "%";
} else {
progressText = "完成";
}
mPaint.setTextSize(mTextSize);
float[] widths = new float[progressText.length() - 1];
mPaint.getTextWidths(progressText, 0, progressText.length() - 1, widths);
float textWidth = 0;
for (int i=0;i<widths.length;i++){
textWidth+=widths[i];
}
float textHeightinVer = mHeight/2-mPaint.descent()+(mPaint.descent()-mPaint.ascent())/2;
canvas.drawText(progressText,mRadius-textWidth/widths.length,textHeightinVer,mPaint);
}
要注意的是,画圆的顺序不能乱了,必须是最低下的先画,再是画上面的进度条,这是一个扇形,再画里面的内圆,最后画中间的文字。
最后一个是通过布局来实现的,一个相对布局,里面放的是一个button和一个进度条,重叠在一起,通过更新progressbar的进度来实现,这个可以保留button的特点。实现也挺简单的。
核心代码:
布局文件
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginTop="16dp">
<ProgressBar
android:id="@+id/pb_movie_progress_id"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerHorizontal="true"
android:max="100"
android:progress="0"
android:background="#999191"
android:progressDrawable="@drawable/progress_selector"
android:secondaryProgress="0"
/>
<Button
android:id="@+id/bt_registe"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textColor="@color/base_white"
android:text="注册"
android:background="@drawable/btn_selector"
android:textSize="@dimen/text_commen_size" />
</RelativeLayout>
里面的进度条的图可以自己定义
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:id="@android:id/progress">
<clip
android:clipOrientation="horizontal"
android:drawable="@drawable/progress_drawable"
android:gravity="left" />
</item>
</layer-list>
搞定!