自定义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;
}
}
发布评论
热门评论区: