最近项目需求有个音频播放进度条类似这种的。之前进度条都是用progressbar搞得。但是没有滑块,于是就想到了seekbar,这个是有滑块的Thumb。
这里说明一下Thumb 滑块样式很重要,我们可以在drawable里面自定义滑块的样式,也可以用图片等代替。
这里先附上完整代码运行后的图以及原生seekbar的样式。
上面的自定义的,下面是原生的,感觉原生其他还是蛮好看的,点击按下还有效果(自定义也可以实现自己想要的效果,这里需求了没有,就不在赘述)。
现在根据需求自定义我们的view在
public class CustomSeekBar extends AppCompatSeekBar {}
自定义seekbar里面
我们需要画三个东西,一个是进度条 一个是文字 一个是滑块。
附上代码
private void initPaint() {
//文字画笔
mTextPaint = new Paint();
mTextPaint.setARGB(255, 255, 255, 255);
mTextPaint.setAntiAlias(true);
mTextPaint.setTextSize(mThumb.getMinimumHeight() * 3 / 6);//文字大小为滑块高度的2/3
mTextPaint.setTextAlign(Paint.Align.CENTER); // 设置文本对齐方式,居中对齐
//进度画笔
mLinePaint = new Paint();
mLinePaint.setAntiAlias(true);
//滑块画笔
mCirclePaint = new Paint();
mCirclePaint.setColor(getResources().getColor(R.color.colorPrimary));
mCirclePaint.setAntiAlias(true);
mCirclePaint.setStyle(Paint.Style.FILL_AND_STROKE);
}
我们可以看到代码中文字的大小和高度我们不可能在布局文件中设置,只能根据滑块的高度去设置,所以我们首先需要
在CustomSeekbar构造器中初始化一个我们想要的滑块样式
private Drawable mThumb;
//设置滑块样式
mThumb = context.getResources().getDrawable(R.drawable.circle_thumb);
setThumb(mThumb);
setThumbOffset(0);
其中R.drawable.circle_thumb很简单,不懂的可以下载demo看里面的具体内容。
上面的初始化了画笔和滑块样式。
下面进入测量 布局 绘制过程。
首先在omMeasuer里面我们需要根据滑块的尺寸去确定大小,上面也提到,我们的文字大小就是根据滑块的尺寸确定,所以我们需要确定滑块的大小
heightMeasureSpec = MeasureSpec.makeMeasureSpec(mThumb.getMinimumHeight(), MeasureSpec.EXACTLY);
这里我们也可以获得进度条的宽度
mViewWidth = MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight();
我们的布局不需要做其他处理,所以直接进入onDraw绘制阶段。
由于我们能确定就是滑块的大小,所以我们需要获得滑块的坐标然后来进行绘制。
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//获取滑块坐标
Rect thumbRect = getThumb().getBounds();
mCenterX = thumbRect.centerX();//中心X坐标
mCenterY = thumbRect.centerY(); //中心Y坐标
mThumbHeight = thumbRect.height();//滑块高度
//绘制进度条
drawRect(canvas);
//绘制滑块
RectF rectF=new RectF(thumbRect.left,thumbRect.top,thumbRect.right,thumbRect.bottom);
canvas.drawRoundRect(rectF,50,50,mCirclePaint);
//绘制进度文字
drawProgress(canvas);
}
这里的50是矩形两端圆的半径。这里我随便写上去的,也可根据算法得到,好像是外接圆公式,MMP,学的东西都忘记了。
下面贴出来进度条和文字的绘制,基本和滑块一样。
/**
* 绘制进度条
* @param canvas
*/
private void drawRect(Canvas canvas) {
//绘制左边的进度
mRectF = new RectF();
mRectF.left = 0;
mRectF.right = mCenterX;
mRectF.top = mCenterY - mThumbHeight / 13;
mRectF.bottom = mCenterY + mThumbHeight / 13;
mLinePaint.setColor(getResources().getColor(R.color.colorPrimary));
canvas.drawRoundRect(mRectF, mThumbHeight / 13, mThumbHeight / 13, mLinePaint);
//绘制右边剩余的进度
mRectF.left= mCenterX;
mRectF.right = mViewWidth;
mRectF.top = mCenterY - mThumbHeight / 15;
mRectF.bottom = mCenterY + mThumbHeight / 15;
mLinePaint.setARGB(255,255,65,130);
canvas.drawRoundRect(mRectF, mThumbHeight / 15, mThumbHeight /15, mLinePaint);
}
/**
* 绘制文本
* @param canvas
*/
private void drawProgress(Canvas canvas) {
String progress;
float score = mMaxShowValue*getProgress()/getMax();
switch (mPrecisionMode) {
case 1:
float f1Score = (float)(Math.round(score*10))/10;
progress="" + f1Score;
break;
case 2:
DecimalFormat fnum = new DecimalFormat("##0.00");
progress=fnum.format(score);
break;
default:
progress="" +(int)score;
break;
}
Rect bounds = new Rect();
mTextPaint.getTextBounds(progress, 0, progress.length(), bounds);
int mTextHeight = bounds.height();
// float mTextWidth = mTextPaint.measureText(progress);
canvas.drawText(progress, mCenterX, mCenterY + mTextHeight/2, mTextPaint);
}
项目中右边的进度条是不显示的,可以不绘制就行。
我们这里也可以让seekbar不能拖动直接设置seekbar.setEnabled(false)即可。
然后就在布局文件中引用该类就可以了。
Demo下载地址https://download.csdn.net/download/zhangcainiao007/11218198