胸怀万里世界, 放眼无限未来。这篇文章主要讲述Android技术分享| 自定义View实现使用更方便的SeekBar相关的知识,希望能为你提供帮助。
前言
android中自带的SeekBar个人感觉用起来很麻烦,调整一些颜色之类的需要单独写一个XML文件,内容感觉也很啰嗦。刚好我们的白板Demo开发中需要用到SeekBar,所以干脆实现了一个满足基本功能的SeekBar,支持在xml布局中指定各种颜色属性,也支持代码动态设置颜色。用起来更顺心一些。
SeekBar的代码请查看Github地址:白板Demo,Demo地址请:点击这里
即拿即用,非常方便;
p(记得将res/values/styles.xml
中的属性一并复制走)
效果
文章图片
实现
由于不涉及到动画,这种自定义View做起来还是相当简单的。首先在
res/values/styles.xml
文件中定义好自己需要的属性,我这里贴上我定义的属性:<
declare-styleable name="SeekBarWidget">
<
attr name="seek_maxProgress" format="integer" />
<
!-- 最大progress -->
<
attr name="seek_minProgress" format="integer" />
<
!-- 最小progress -->
<
attr name="seek_progress" format="integer" />
<
!-- 当前progress(默认值) -->
<
attr name="seek_circleRadius" format="dimension" />
<
!-- seekBar中间圆形的半径 -->
<
attr name="seek_circleStrokeWidth" format="dimension" />
<
!-- seekBar中间圆形外的border -->
<
attr name="seek_lineHeight" format="dimension" />
<
!-- lineHeight有点词不达意,其实是进度条的高度 -->
<
attr name="seek_backgroundColor" format="color" />
<
!-- 进度条的背景色 -->
<
attr name="seek_circleStrokeColor" format="color" />
<
!-- border的颜色 -->
<
attr name="seek_maxColor" format="color" />
<
!-- 进度条的前景色 -->
<
attr name="seek_startColor" format="color" />
<
!-- 如果需要渐变色则设置此属性,否则这条属性置空即可 -->
<
/declare-styleable>
属性定义好以后,在View的构造中解析一下:
public SeekBarWidget(Context context)
this(context, null);
public SeekBarWidget(Context context, @Nullable AttributeSet attrs)
this(context, attrs, 0);
public SeekBarWidget(Context context, @Nullable AttributeSet attrs, int defStyleAttr)
super(context, attrs, defStyleAttr);
if (null != attrs)
TypedArray typedArray = getResources().obtainAttributes(attrs, R.styleable.SeekBarWidget);
minProgress = typedArray.getInt(R.styleable.SeekBarWidget_seek_minProgress, 0);
maxProgress = typedArray.getInt(R.styleable.SeekBarWidget_seek_maxProgress, 100) - minProgress;
progress = typedArray.getInt(R.styleable.SeekBarWidget_seek_progress, 0) - minProgress;
if (progress <
0) progress = minProgress;
circleRadius = typedArray.getDimension(R.styleable.SeekBarWidget_seek_circleRadius, 20f);
circleStrokeWidth = typedArray.getDimension(R.styleable.SeekBarWidget_seek_circleStrokeWidth, 5f);
lineHeight = typedArray.getDimension(R.styleable.SeekBarWidget_seek_lineHeight, 5f);
backgroundColor = typedArray.getColor(R.styleable.SeekBarWidget_seek_backgroundColor, Color.parseColor("#F0F0F0"));
circleStrokeColor = typedArray.getColor(R.styleable.SeekBarWidget_seek_circleStrokeColor, Color.WHITE);
int maxColor = typedArray.getColor(R.styleable.SeekBarWidget_seek_maxColor, Color.RED);
int startColor = typedArray.getColor(R.styleable.SeekBarWidget_seek_startColor, maxColor);
colorTransition = new ColorTransition(startColor, maxColor);
typedArray.recycle();
percentage = progress * 1.0f / maxProgress;
horizontalPadding = circleRadius * 2 + circleStrokeWidth * 2 + getPaddingStart() + getPaddingEnd();
mPaddingLeft = horizontalPadding - getPaddingEnd() - circleRadius - circleStrokeWidth;
return;
maxProgress = 100;
minProgress = 0;
circleRadius = 20;
circleStrokeWidth = 5;
lineHeight = 5;
backgroundColor = Color.parseColor("#F0F0F0");
colorTransition = new ColorTransition(Color.WHITE, Color.RED);
circleStrokeColor = Color.WHITE;
horizontalPadding = circleRadius * 2 + circleStrokeWidth * 2 + getPaddingStart() + getPaddingEnd();
mPaddingLeft = horizontalPadding - getPaddingEnd() - circleRadius - circleStrokeWidth;
接下来是
onMeasure
和onDraw
,由于我的应用场景宽高已经固定好了,所以没有写onMeasure
,有需求的朋友可以自己实现一下~而绘制的思路很简单:
- 先绘制一条背景色的线,线的高度由外部指定。(设置StrokeCap为ROUND)
- 再绘制一条前景色的线,线高度同样由外部指定,这里我读取的是同一个属性
lineHeight
,也可以根据需求不同设置不一样的高度; p - 接下来绘制seekBar的圆,这里border也直接使用
drawCircle
来实现,先绘制border。(circleRadius + circleStrokeWidth / 2f) - 最后绘制中间的圆
@Override
protected void onDraw(Canvas canvas)
final int width = (int) (getMeasuredWidth() - horizontalPadding);
final int height = getMeasuredHeight();
paint.setColor(backgroundColor);
paint.setStrokeWidth(lineHeight);
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setStrokeCap(Paint.Cap.ROUND);
canvas.drawLine(mPaddingLeft, height >
>
1, mPaddingLeft + width, height >
>
1, paint);
//float percentage = progress / maxProgress;
int currColor = colorTransition.getValue(percentage);
paint.setColor(currColor);
canvas.drawLine(mPaddingLeft, height >
>
1, mPaddingLeft + width * percentage, height >
>
1, paint);
// draw circle border
paint.setColor(circleStrokeColor);
canvas.drawCircle(mPaddingLeft + width * percentage, height >
>
1, circleRadius + (circleStrokeWidth / 2f), paint);
// draw circle inside color
paint.setColor(currColor);
canvas.drawCircle(mPaddingLeft + width * percentage, height >
>
1, circleRadius, paint);
最后,处理一下onTouch事件。思路也很简单,从down、move、up事件中判断一下是否为横向滚动,是的话计算一下距离,更改progress进度并通知View重新绘制即可:
private float downX;
private float downY;
@Override
public boolean onTouchEvent(MotionEvent event)
boolean intercept = false;
switch (event.getAction())
case MotionEvent.ACTION_DOWN:
downX = event.getX();
downY = event.getY();
intercept = true;
break;
case MotionEvent.ACTION_MOVE:
float moveX = event.getX();
float moveY = event.getY();
float xMove = Math.abs(moveX - downX) - Math.abs(moveY - downY);
if (xMove >
0f)
float hX = moveX - downX;
boolean toLeft = hX <
0.0f;
float movePercent = Math.abs(hX) / getMeasuredWidth();
if (percentage <
1.0f &
&
!toLeft)
percentage += movePercent;
else if (percentage >
0f &
&
toLeft)
percentage -= movePercent;
if (percentage <
0f) percentage = 0f;
if (percentage >
1f) percentage = 1f;
progress = (int) Math.floor(percentage * maxProgress);
intercept = true;
downX = moveX;
downY = moveY;
postInvalidate();
if (null != mListener &
&
beforeProgress != getProgress())
beforeProgress = getProgress();
mListener.onProgress(getProgress());
break;
case MotionEvent.ACTION_UP:
break;
return intercept || super.onTouchEvent(event);
//return true;
@Override
public boolean dispatchTouchEvent(MotionEvent event)
getParent().requestDisallowInterceptTouchEvent(true);
return super.dispatchTouchEvent(event);
OK,一个复制即用的自定义SeekBar便完成了。比官方原版的SeekBar使用起来顺眼多了(??ω?)?
(欢迎下载Demo玩一玩!Demo地址)
【Android技术分享| 自定义View实现使用更方便的SeekBar】
文章图片
推荐阅读
- Kubernetes官方java客户端之七(patch操作)
- 考研刷题小程序云开发实战-基础知识储备
- #yyds干货盘点# springcloud整合gateway实现网关全局过滤器功能
- 如何检测假冒U盘:扩容U盘鉴别
- u盘使电脑系统变卡如何处理?
- 教你防范U盘木马病毒自动运行的办法
- u盘如何重启图文详细教程
- 解除U盘写保护的办法
- 运用u盘的时候USB插口漏电怎样回事