您的位置:首页 > 移动开发 > Android开发

Android自定义SeekBar,带开始值结束值和Thumb上方滑动的Text

2017-08-28 19:08 706 查看
之前根据网友的博文写了一个Demo(点击打开链接)但是这个Demo用到attr,layout color,还有其他的类,给使用者造成很多麻烦,我想,这样的自定义控件为啥不用一个类来完成呢,这样直接复制过来就能用,于是我彻底的封装了这个自定义的SeekBar,做到了一个类完成所有功能,而且代码量也不多。效果图:



    原理,其实我不是自定义SeekBar,我是自定义了一个RelativeLayout,里面放了三个TextView和一个SeekBar,用代码控制他们的位置,实现动态显示值。

    首先,向自定义的RelativeLayout用代码添加子控件,这样就不用XML来布局了

private void addChildens() {
textView = new ProgressTextView(mContext);
textView.setId(View.generateViewId());
LayoutParams lpTextView = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 40);
textView.setLayoutParams(lpTextView);
addView(textView);

mSeekBar = new SeekBar(mContext);
mSeekBar.setId(View.generateViewId());
mSeekBar.setMax(seekBarMax);
mSeekBar.setMinimumHeight(12);
if (thumDrawable > 0) {
mSeekBar.setThumb(ContextCompat.getDrawable(mContext, thumDrawable));
}
if (seekBarDrawable > 0) {
mSeekBar.setBackgroundResource(seekBarDrawable);
}
mSeekBar.setPadding(0, 0, 0, 0);
mSeekBar.setThumbOffset(0);
LayoutParams lpSeekBar = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
lpSeekBar.addRule(RelativeLayout.BELOW, textView.getId());
mSeekBar.setLayoutParams(lpSeekBar);
addView(mSeekBar);

mTvStart = new TextView(mContext);
LayoutParams lpStart = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
lpStart.addRule(ALIGN_PARENT_LEFT);
lpStart.addRule(RelativeLayout.BELOW, mSeekBar.getId());
mTvStart.setLayoutParams(lpStart);
addView(mTvStart);

mTvEnd = new TextView(mContext);
LayoutParams lpEnd = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
lpEnd.addRule(ALIGN_PARENT_RIGHT);
lpEnd.addRule(RelativeLayout.BELOW, mSeekBar.getId());
mTvEnd.setLayoutParams(lpEnd);
addView(mTvEnd);
}    然后就是自定义的一个浮标并显示SeekBar的值:
class ProgressTextView extends View {
private int mHeight;
private int mWidth;
private double mOneProgressWidth;
private int mCurProgress = 0;
private String mProgressText = "";
private Paint mPaint;
private float mThumbOffset;
private int mTextSize = 12;
private float thumWidth;

private String mTextColor = "#303F9F";//default color of column

public ProgressTextView(Context context) {
super(context);
initObserver();
}

@RequiresApi(api = Build.VERSION_CODES.M)
public ProgressTextView(Context context, AttributeSet attrs) {
super(context, attrs);
if (null != context && attrs != null) {
mThumbOffset = thumWidth / 2;
}
initObserver();
}

private void initObserver() {
ViewTreeObserver vto = getViewTreeObserver();
vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {

@Override
public boolean onPreDraw() {
mHeight = getMeasuredHeight();
mWidth = getMeasuredWidth();
initPaint();
initData();
return true;
}
});
}

private void initPaint() {
mPaint = new Paint();
mPaint.setTextSize(mTextSize);
mPaint.setTextAlign(Paint.Align.CENTER);
mPaint.setColor(Color.parseColor(mTextColor));
}

private void initData() {
mOneProgressWidth = (double) (mWidth - 2 * mThumbOffset) / (seekBarMax);
}

public void setTextSize(int mTextSize) {
this.mTextSize = mTextSize;
invalidate();
}

@Override
protected void onDraw(Canvas canvas) {
initPaint();
drawText(canvas);
super.onDraw(canvas);
}

//设置字体居中显示
private void drawText(Canvas canvas) {
float x = (float) (mCurProgress * mOneProgressWidth);
float textWidth = mPaint.measureText(mProgressText);
float textOffset = textWidth / 2;
if (x + textOffset > mWidth - mThumbOffset) {//超过view的右边
float exWidth = x + textOffset - (mWidth - mThumbOffset);
x -= exWidth;//避免超过右边
}
if (x + mThumbOffset < textOffset) {//超过左边
float exWidth = textOffset - (x + mThumbOffset);
x += exWidth;//避免超过左边
}
canvas.translate(mThumbOffset, 0);
canvas.drawText(mProgressText, x, mHeight, mPaint);
}

//设置显示的进度位置和字符串
public void setProgress(int progress, String showText) {
mCurProgress = progress;
mProgressText = showText;
invalidate();
}
}我还写了监听器和各种setter,保证这个自定义View的可操作性
Demo源码
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息