公司需要如上图这种样式的SeekBar,写项目时 觉得SeekBar自身就有设置按钮样式,改变进度条颜色的api,但是实际使用中存在几个问题:1.seekBar的按钮thumb默认是thumboffset=0,按钮在seekBar左边是只能显示一半。2. 每次通过setThumb()改变按钮图片,thumbOffset每次都会被重置为0 。 3.progress 并不能动态充满
针对问题1:使用paddingLeft 可以让按钮与seekBar左边对齐 2. 进度条自己使用画笔自己画 代码如下
canvas.drawRoundRect(new RectF(0, top, thumbLeft, bottom), mRadius, mRadius, mProgressPaint); //绘制进度条颜色 也就是绘制一个矩阵 这里的top,bottom是seekBar的top,bottom,thumbLeft是按钮的左边距离seekBar左边的距离,mRadius是矩阵的圆角
因为进度条是自己画上去的,所以进度条会遮盖住按钮,这里的解决方法就是在原来thumb按钮的位置在重新画一个一模一样的按钮:
canvas.drawBitmap(BitmapFactory.decodeResource(getResources(),mMaskThumb),getThumb().getBounds().left,top,null);
这里mMaskThumb就是按钮的样式,如此就解决了进度条遮盖了按钮的问题。
其实只是继承SeekBar的基础上改了一点,之前没想到坑这么多,其实自己去自定义一个view也不会太麻烦。
控件代码如下:
package com.job.android.views; import android.content.Context; import android.content.res.TypedArray; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.RectF; import android.support.v7.widget.AppCompatSeekBar; import android.util.AttributeSet; import android.view.MotionEvent; import com.job.android.R; import com.jobs.lib_v1.device.DeviceUtil; import java.sql.Time; import java.util.Timer; import java.util.TimerTask; /** * Created by sima.tu on 2018/9/18. */ public class VerifySeekBar extends AppCompatSeekBar { private String mVerifyText; private int mTextSize; private Paint mTextPaint; private Paint mProgressPaint; private int mRadius = DeviceUtil.dip2px(8f); private int mMaskThumb; private int type = 1; private static final int DEFAULT_THUMB = 1; private static final int CORRECT_THUMB = 2; private static final int WRONG_THUMB = 3; public int getType() { return type; } public void setType(int type) { this.type = type; } public VerifySeekBar(Context context) { super(context); init(context, null); } public VerifySeekBar(Context context, AttributeSet attrs) { super(context, attrs); init(context, attrs); } public VerifySeekBar(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context, attrs); } private void init(Context context, AttributeSet attrs) { TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.VerifySeekBar); int count = array.getIndexCount(); for (int i = 0; i < count; i++) { int index = array.getIndex(i); switch (index) { case R.styleable.VerifySeekBar_verifyText: mVerifyText = array.getString(index); break; case R.styleable.VerifySeekBar_text_Size: mTextSize = array.getDimensionPixelSize(index, 16); break; } } array.recycle(); mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mTextPaint.setTextSize(mTextSize); mTextPaint.setColor(getResources().getColor(R.color.grey_999999)); } /** * 绘制 "滑动完成验证"的提示文字 * * @param canvas */ @Override protected synchronized void onDraw(Canvas canvas) { super.onDraw(canvas); if (getThumb() == null) { return; } canvas.save(); Rect rect = new Rect(); int textLength = mVerifyText == null ? 0 : mVerifyText.length(); mTextPaint.getTextBounds(mVerifyText, 0, textLength, rect); int startX = (getWidth() - rect.width()) / 2 + getThumb().getIntrinsicWidth() / 2; int startY = getHeight() / 2 + rect.height() / 2; //绘制滑块中的提示文字 canvas.drawText(mVerifyText, startX, startY, mTextPaint); int thumbLeft = getThumb().getBounds().left + 70; // thumb按钮的左边 int top = getThumb().getBounds().top; int bottom = getThumb().getBounds().bottom; //初始位置不需要绘制进度 if ( null == getThumb()) { canvas.restore(); return; } mProgressPaint = new Paint(); mProgressPaint.setStyle(Paint.Style.FILL);//设置填充样式 // mProgressPaint.setStrokeWidth(15);//设置画笔宽度 switch (getType()) { case DEFAULT_THUMB: mProgressPaint.setColor(getResources().getColor(R.color.progress_default)); mMaskThumb = R.drawable.slider_button_default; break; case CORRECT_THUMB: mProgressPaint.setColor(getResources().getColor(R.color.progress_success)); mMaskThumb = R.drawable.slider_button_success; break; case WRONG_THUMB: mProgressPaint.setColor(getResources().getColor(R.color.progress_failed)); mMaskThumb = R.drawable.slider_button_failed; break; } canvas.drawRoundRect(new RectF(0, top, thumbLeft, bottom), mRadius, mRadius, mProgressPaint); //绘制进度条颜色 也就是绘制一个矩阵 //这里clipPath获取边上的角 来着色 // Path path = new Path(); // Path path1 = new Path(); // //左上角的缺角 // canvas.save(); //// canvas.clipRect(thumbLeft - DeviceUtil.dip2px(8), top, thumbLeft, top + DeviceUtil.dip2px(8), Region.Op.INTERSECT); //// canvas.drawColor(Color.parseColor("#ffc8c7")); //// canvas.drawCircle(thumbLeft - DeviceUtil.dip2px(8),top + DeviceUtil.dip2px(8),DeviceUtil.dip2px(8),mProgressPaint); //// canvas.drawRoundRect(thumbLeft,top,thumbLeft + DeviceUtil.dip2px(8),top + DeviceUtil.dip2px(8),0,0,mProgressPaint); //// canvas.restore(); // // path.moveTo(thumbLeft - mRadius, top); // path.lineTo(thumbLeft - mRadius, top + mRadius); // path.lineTo(thumbLeft, top + mRadius); // path.lineTo(thumbLeft, top); // path.close(); // path1.addCircle(thumbLeft - mRadius, top + mRadius, mRadius, Path.Direction.CW); // path.op(path1, Path.Op.DIFFERENCE); // canvas.drawPath(path, mProgressPaint); // canvas.restore(); // // //右上角的缺角 第1次不同于第2次的部分显示 // canvas.save(); // path.moveTo(thumbLeft, top); // path.lineTo(thumbLeft, top + mRadius); // path.lineTo(thumbLeft + mRadius, top + mRadius); // path.lineTo(thumbLeft + mRadius, top); // path.close(); // // path1.addCircle(thumbLeft + mRadius, top + mRadius, mRadius, Path.Direction.CW); // path.op(path1, Path.Op.DIFFERENCE); // canvas.drawPath(path, mProgressPaint); // canvas.restore(); // path1.reset(); // //右下角的 // canvas.save(); // path.moveTo(thumbLeft, bottom - mRadius); // path.lineTo(thumbLeft + mRadius, bottom - mRadius); // path.lineTo(thumbLeft + mRadius, bottom); // path.lineTo(thumbLeft, bottom); // path.close(); // path1.addCircle(thumbLeft + mRadius, bottom - mRadius, mRadius, Path.Direction.CW); // path.op(path1, Path.Op.DIFFERENCE); // canvas.drawPath(path, mProgressPaint); // canvas.restore(); // //左下角的 // path.moveTo(thumbLeft - mRadius, bottom); // path.lineTo(thumbLeft, bottom - mRadius); // path.lineTo(thumbLeft, bottom - mRadius); // path.lineTo(thumbLeft, bottom); // // path.close(); // path1.addCircle(thumbLeft - mRadius, bottom - mRadius, mRadius, Path.Direction.CW); // path.op(path1, Path.Op.DIFFERENCE); // canvas.drawPath(path, mProgressPaint); //直接在原来thumb上盖一个一模一样的图标 canvas.drawBitmap(BitmapFactory.decodeResource(getResources(),mMaskThumb),getThumb().getBounds().left,top,null); if(getType() == WRONG_THUMB){ timerTask = new TimerTask() { @Override public void run() { setProgress(0); timerTask.cancel(); } }; new Timer().schedule(timerTask,500); // 延迟0.5秒 } } private TimerTask timerTask; /** * 禁用点击非thumb按钮区域的点击事件 * @param event * @return */ @Override public boolean dispatchTouchEvent(MotionEvent event) { if (getThumb() == null) { return false; } Rect thumbRect = getThumb() == null ? null : getThumb().getBounds(); int thumbLeft = thumbRect.left; int thumbRight = thumbRect.right; int thumbTop = thumbRect.top; int thumbBottom = getThumb().getBounds().bottom; int eventX = (int) event.getX(); int eventY = (int) event.getY(); if (event.getAction() == MotionEvent.ACTION_DOWN) { if (eventX <= thumbLeft || eventX >= thumbRight || eventY <= thumbTop || eventY >= thumbBottom) { return false; } } return super.dispatchTouchEvent(event); } /** * 清除提示滑动的文字 使用的方法是直接设置画笔颜色透明 */ public void dismissDragText(){ if(getProgress() == 0){ mTextPaint.setColor(getResources().getColor(R.color.grey_999999)); }else { mTextPaint.setColor(getResources().getColor(R.color.transparent)); } invalidate(); } }