前言
在开发中,经常会遇到SeekBar组件的开发,一个高效的自定义SeekBar显得尤为重要,笔者刚好也在项目中大量使用带有数字的拖拽进度条,在深思熟虑后,打算从继承源码形式上,把数字绘制在拖拽进度条上,让拖拽的时候时刻去更新数字。这种实现方式不到100行代码,代码极其精简,功能极其好用,另外,这种方案可以用于各种组件绘制在进度条上方,这块的实现就看需求的具体效果
本例子中高仿抖音的进度拖拽效果,实现效果如下
实现思路
继承SeekBar,自定义属性在onDraw方法增加数字的绘制和数字阴影的绘制实现分析
1、快速使用
在xml直接使用,其监听进度变化同SeekBar组件
<com.baseui.seekbar.NumberSeekBarandroid:layout_width="match_parent"android:layout_height="54dp"android:max="100"android:paddingStart="24dp"android:paddingEnd="24dp"android:progressDrawable="@drawable/progress_seek_bar_beauty"android:thumb="@drawable/icon_beauty_seek_bar_thumb"app:textColor="@color/white"app:textMarginBottom="2dp"app:textShadowColor="#80000000"app:textShadowOffsetX="0dp"app:textShadowOffsetY="0dp"app:textShadowRadius="2dp"app:textSize="12sp"app:withText="true"app:withTextShadow="true"tools:progress="50"/>
2、自定义属性
在attr中增加自定义的属性
<resources><declare-styleable name="InheritedSeekBar"><attr name="withText" format="boolean" /><attr name="textSize" format="dimension" /><attr name="textColor" format="color" /><attr name="textMarginBottom" format="dimension" /><attr name="withTextShadow" format="boolean" /><attr name="textShadowColor" format="color" /><attr name="textShadowOffsetX" format="dimension" /><attr name="textShadowOffsetY" format="dimension" /><attr name="textShadowRadius" format="dimension" /></declare-styleable></resources>
withText:是否带有进度值textSize:进度值的大小textColor:进度值的颜色textMarginBottom:进度值底边距withTextShadow:是否带有进度值的阴影textShadowColor:进度值阴影的颜色textShadowOffsetX:进度值阴影的x坐标偏移textShadowOffsetY:进度值阴影的y坐标偏移textShadowRadius:进度值阴影的圆角
3、获取属性
通过attributeSet
获取自定义属性,同时获取进度的属性和进度阴影的属性
class NumberSeekBar @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : AppCompatSeekBar(context, attrs, defStyleAttr) {private val textPaint = Paint()private var withText: Boolean = falseprivate var textSize: Float = 0fprivate var textColor: Int = Color.BLACKprivate var textMarginBottom: Int = 0private var withTextShadow = falseprivate var textShadowColor = Color.BLACKprivate var textShadowRadius = 0private var textShadowOffsetX = 0private var textShadowOffsetY = 0init {init(context, attrs)}private fun init(context: Context, attributeSet: AttributeSet?) {val a: TypedArray = context.obtainStyledAttributes(attributeSet, R.styleable.InheritedSeekBar)// 获取进度的属性withText = a.getBoolean(R.styleable.InheritedSeekBar_withText, false)if (withText) {textSize = a.getDimensionPixelSize(R.styleable.InheritedSeekBar_textSize,TypedValue.applyDimension(PLEX_UNIT_SP,12f,context.resources.displayMetrics).toInt()).toFloat()textColor = a.getColor(R.styleable.InheritedSeekBar_textColor, textColor)textMarginBottom = a.getDimensionPixelSize(R.styleable.InheritedSeekBar_textMarginBottom, 0)}// 获取进度阴影的属性withTextShadow = a.getBoolean(R.styleable.InheritedSeekBar_withTextShadow, false)if (withTextShadow) {textShadowColor = a.getColor(R.styleable.InheritedSeekBar_textShadowColor, textShadowColor)textShadowRadius = a.getDimensionPixelSize(R.styleable.InheritedSeekBar_textShadowRadius, 0)textShadowOffsetX = a.getDimensionPixelOffset(R.styleable.InheritedSeekBar_textShadowOffsetX, 0)textShadowOffsetY = a.getDimensionPixelOffset(R.styleable.InheritedSeekBar_textShadowOffsetY, 0)}a.recycle()// 对画笔设置值和阴影if (withText) {textPaint.textSize = textSizetextPaint.color = textColortextPaint.textAlign = Paint.Align.CENTER}if (withTextShadow) {textPaint.setShadowLayer(textShadowRadius.toFloat(), textShadowOffsetX.toFloat(),textShadowOffsetY.toFloat(), textShadowColor)}}}
4、绘制数字和阴影
通过复写onDraw
方法,经过计算偏移量后,在进度拖拽的上方绘制数字
override fun onDraw(canvas: Canvas) {super.onDraw(canvas)if (withText) {drawText(canvas)}}private fun drawText(canvas: Canvas) {val saveCount = canvas.save()val thumbTopY = thumb.bounds.top// 计算拖拽组件的中点val thumbCenterX = paddingStart + progress.toFloat() / max * (width - paddingStart - paddingEnd)canvas.drawText(progress.toString(), thumbCenterX, thumbTopY.toFloat() - textMarginBottom, textPaint)canvas.restoreToCount(saveCount)}
5、进度条颜色
对于进度条颜色是layer-list
,可以设置进度的背景和进度颜色值,而进度拖拽组件,其实就是个圆形的Icon图片而已
android:progressDrawable="@drawable/progress_seek_bar"android:thumb="@drawable/icon_beauty_seek_bar_thumb"
在progress_seek_bar
设置进度成黄色,背景成少许透明的灰黑色
<?xml version="1.0" encoding="utf-8"?><layer-list xmlns:android="/apk/res/android"><itemandroid:id="@android:id/background"android:gravity="center_vertical"><shape><solid android:color="#29ffffff" /><corners android:radius="3dp" /><size android:height="3dp" /></shape></item><itemandroid:id="@android:id/secondaryProgress"android:gravity="center_vertical"><clip><shape><solid android:color="#29ffffff" /><corners android:radius="3dp" /><size android:height="3dp" /></shape></clip></item><itemandroid:id="@android:id/progress"android:gravity="center_vertical"><clip><shape><solid android:color="#ffffe000" /><corners android:radius="3dp" /><size android:height="3dp" /></shape></clip></item></layer-list>