自定义SeekBar样式,自定义滑块
系统自带的SeekBar真是太难看了,不能容忍! 只能自己做了,先来张效果图
1、带数字的SeekBar,数字随着滑块移动
2、滑块在进度条下面
下面是实现方法:
public class MSeekBar extends View { ~~~~~ }
继承View,重写onMeasure方法,主要是计算这个View的高度,文本高度+竖线高度+进度条高度+间隔高度
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { float height = textHeight + lineHeight + seekHeight + seekBitmap.getHeight() + 5 * interval; super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec((int) height, heightMeasureSpec)); init = true; }
然后就是重新onDraw方法进行分别绘制
@Override protected void onDraw(Canvas canvas) { if (!init) { return; } String text = "+" + selectNum; float textWidth = mTextPaint.measureText(text); float textX = mPositionX - textWidth / 2; if (textX < seekOffsetX) { textX = seekOffsetX; } else if (textX > getWidth() - seekOffsetX - textWidth) { textX = getWidth() - seekOffsetX - textWidth; } //绘制文本 mTextPaint.setColor(textColor); canvas.drawText(text, textX, textHeight, mTextPaint); //绘制间隔线 mTextPaint.setColor(seekColor); canvas.drawRect(mPositionX, textHeight + interval, mPositionX + lineWidth, textHeight + lineHeight + interval, mTextPaint); //绘制背景进度条 mTextPaint.setColor(bgColor); canvas.drawRoundRect(seekOffsetX, textHeight + lineHeight + interval * 2, getWidth() - seekOffsetX, textHeight + lineHeight + seekHeight + 2 * interval, radius, radius, mTextPaint); //----start-----绘制进度条 int sc = canvas.saveLayer(seekOffsetX, textHeight + lineHeight + interval * 2, getWidth() - seekOffsetX, textHeight + lineHeight + seekHeight + 2 * interval, null, Canvas.ALL_SAVE_FLAG); //绘制进度条 mTextPaint.setColor(seekColor); canvas.drawRoundRect(seekOffsetX, textHeight + lineHeight + interval * 2, getWidth() - seekOffsetX, textHeight + lineHeight + seekHeight + 2 * interval, radius, radius, mTextPaint); //裁剪进度条 mTextPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); canvas.drawRect(mPositionX, textHeight + lineHeight + interval * 2, getWidth() - seekOffsetX, textHeight + lineHeight + seekHeight + 2 * interval, mTextPaint); canvas.restoreToCount(sc); mTextPaint.setXfermode(null); //----end-----绘制进度条 //绘制游标 canvas.drawBitmap(seekBitmap, mPositionX - seekOffsetX, bitmapTop, mTextPaint); }
上面有备注。
重新onTouch方法,进行事件判断:
private float startX, startY; private float diffX; @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: startX = event.getX(); startY = event.getY(); diffX = startX - mPositionX; return checkEvent(startX, startY); case MotionEvent.ACTION_MOVE: float tempX = event.getX() - diffX; if (tempX >= seekOffsetX && tempX <= getWidth() - seekOffsetX) { mPositionX = tempX; } else { if (tempX < seekOffsetX) { mPositionX = seekOffsetX; } else { mPositionX = getWidth() - seekOffsetX; } } progress = (mPositionX - seekOffsetX) * 1.0 / (getWidth() - 2 * seekOffsetX); selectNum = (int) (max * progress); if (onSeekBarChangeListener != null) { onSeekBarChangeListener.onProgressChanged(progress, selectNum); } invalidate(); break; } return super.onTouchEvent(event); }
判断手指是否在滑块范围内:
private boolean checkEvent(float x, float y) { return (x >= mPositionX - seekOffsetX && x <= mPositionX + seekOffsetX) && (y >= bitmapTop && y <= bitmapTop + seekBitmap.getHeight()); }
好了,大概思路就是这样。
送上完整的代码如下:
package com.wenwen.nianfo.custom.view; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import com.wenwen.nianfo.R; import com.wenwen.nianfo.utils.CommUtils; import com.wenwen.nianfo.utils.PicUtils; /** * Created by Resmic on 2018/8/13. * Email:xiangyx@wenwen-tech.com * <p> * <p> * describe:自定义SeekBar */ public class MSeekBar extends View { private Bitmap seekBitmap; private Paint mTextPaint; private int selectNum = 0; private int lineHeight = 7; private int lineWidth = 1; private int seekHeight = 10; private int max = 100; private double progress = 0; private int textHeight; private int seekOffsetX; private float interval = 1.5f; private float mPositionX; private float bitmapTop; private int textColor; private int bgColor; private int seekColor; private float radius; private boolean init = false; public MSeekBar(Context context) { super(context); initView(); } public MSeekBar(Context context, AttributeSet attrs) { super(context, attrs); initView(); } private void initView() { seekBitmap = PicUtils.zoomBitmap(PicUtils.res2Bitmap(getContext(), R.mipmap.slider), CommUtils.dip2px(34), CommUtils.dip2px(48)); mTextPaint = new Paint(); mTextPaint.setAntiAlias(true); textColor = getResources().getColor(R.color.color_3); bgColor = Color.parseColor("#EDEFF4"); seekColor = getResources().getColor(R.color.color_2); mTextPaint.setTextSize(CommUtils.dip2px(12)); lineHeight = CommUtils.dip2px(lineHeight); seekHeight = CommUtils.dip2px(seekHeight); lineWidth = CommUtils.dip2px(lineWidth); interval = CommUtils.dip2px(interval); radius = seekHeight / 2; Rect bounds = new Rect(); mTextPaint.getTextBounds("0", 0, 1, bounds); textHeight = bounds.bottom - bounds.top; seekOffsetX = seekBitmap.getWidth() / 2; mPositionX = seekOffsetX; bitmapTop = textHeight + lineHeight + seekHeight + 5 * interval; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { float height = textHeight + lineHeight + seekHeight + seekBitmap.getHeight() + 5 * interval; super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec((int) height, heightMeasureSpec)); init = true; } @Override protected void onDraw(Canvas canvas) { if (!init) { return; } String text = "+" + selectNum; float textWidth = mTextPaint.measureText(text); float textX = mPositionX - textWidth / 2; if (textX < seekOffsetX) { textX = seekOffsetX; } else if (textX > getWidth() - seekOffsetX - textWidth) { textX = getWidth() - seekOffsetX - textWidth; } //绘制文本 mTextPaint.setColor(textColor); canvas.drawText(text, textX, textHeight, mTextPaint); //绘制间隔线 mTextPaint.setColor(seekColor); canvas.drawRect(mPositionX, textHeight + interval, mPositionX + lineWidth, textHeight + lineHeight + interval, mTextPaint); //绘制背景进度条 mTextPaint.setColor(bgColor); canvas.drawRoundRect(seekOffsetX, textHeight + lineHeight + interval * 2, getWidth() - seekOffsetX, textHeight + lineHeight + seekHeight + 2 * interval, radius, radius, mTextPaint); //----start-----绘制进度条 int sc = canvas.saveLayer(seekOffsetX, textHeight + lineHeight + interval * 2, getWidth() - seekOffsetX, textHeight + lineHeight + seekHeight + 2 * interval, null, Canvas.ALL_SAVE_FLAG); //绘制进度条 mTextPaint.setColor(seekColor); canvas.drawRoundRect(seekOffsetX, textHeight + lineHeight + interval * 2, getWidth() - seekOffsetX, textHeight + lineHeight + seekHeight + 2 * interval, radius, radius, mTextPaint); //裁剪进度条 mTextPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); canvas.drawRect(mPositionX, textHeight + lineHeight + interval * 2, getWidth() - seekOffsetX, textHeight + lineHeight + seekHeight + 2 * interval, mTextPaint); canvas.restoreToCount(sc); mTextPaint.setXfermode(null); //----end-----绘制进度条 //绘制游标 canvas.drawBitmap(seekBitmap, mPositionX - seekOffsetX, bitmapTop, mTextPaint); } private float startX, startY; private float diffX; @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: startX = event.getX(); startY = event.getY(); diffX = startX - mPositionX; return checkEvent(startX, startY); case MotionEvent.ACTION_MOVE: float tempX = event.getX() - diffX; if (tempX >= seekOffsetX && tempX <= getWidth() - seekOffsetX) { mPositionX = tempX; } else { if (tempX < seekOffsetX) { mPositionX = seekOffsetX; } else { mPositionX = getWidth() - seekOffsetX; } } progress = (mPositionX - seekOffsetX) * 1.0 / (getWidth() - 2 * seekOffsetX); selectNum = (int) (max * progress); if (onSeekBarChangeListener != null) { onSeekBarChangeListener.onProgressChanged(progress, selectNum); } invalidate(); break; } return super.onTouchEvent(event); } private boolean checkEvent(float x, float y) { return (x >= mPositionX - seekOffsetX && x <= mPositionX + seekOffsetX) && (y >= bitmapTop && y <= bitmapTop + seekBitmap.getHeight()); } public void setMax(int max) { this.max = max; } public void setSelectNum(int selectNum) { if (selectNum < 0 || selectNum > max) { return; } this.selectNum = selectNum; this.progress = selectNum * 1.0 / max; if (progress < 0) { progress = 0; } else if (progress > 100) { progress = 100; } if (onSeekBarChangeListener != null) { onSeekBarChangeListener.onProgressChanged(progress, selectNum); } mPositionX = (float) ((getMeasuredWidth() - seekOffsetX * 2) * progress) + seekOffsetX; postInvalidate(); } public int getSelectNum() { return selectNum; } public interface OnSeekBarChangeListener { void onProgressChanged(double progress, int selectNum); } private OnSeekBarChangeListener onSeekBarChangeListener; public void setOnSeekBarChangeListener(OnSeekBarChangeListener onSeekBarChangeListener) { this.onSeekBarChangeListener = onSeekBarChangeListener; } }
发布评论
热门评论区: