Android自定义view:seekbar的简单处理

最近搬砖,嗯。

有一个seekbar,然后呢需要在thumb下面显示一个进度百分百的文字。然后样式和系统的长的不一样。所以需要简单处理下。

参考资料

正文

思路就那么几种,一种是基于seekbar,设置style,属性啥的。一种是自定义view啥都手写,最后一种就是继承seekbar,用他的逻辑,然后自己画。道理就很简单,自己整就行。

设置style或属性

首先定义xml:

ini 复制代码
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@android:id/background"
        android:gravity="center_vertical|fill_horizontal">
        <shape android:shape="rectangle">
            <size android:height="10dp" />
            <solid android:color="#282b31" />
            <corners android:radius="10dp" />
        </shape>
    </item>
    <item
        android:id="@android:id/progress"
        android:gravity="center_vertical|fill_horizontal">
        <scale android:scaleWidth="100%">
            <shape android:shape="rectangle">
                <size android:height="10dp" />
                <gradient
                    android:angle="0"
                    android:endColor="#aab8d4"
                    android:startColor="#707d93" />
                <corners android:radius="10dp" />
            </shape>
        </scale>
    </item>
    <item android:id="@android:id/secondaryProgress" android:gravity="center_vertical|fill_horizontal">
        <shape android:shape="rectangle">
            <size android:height="10dp" />
            <solid android:color="#282b31" />
            <corners android:radius="10dp" />
        </shape>
    </item>
    
</layer-list>

定义了几个id:

  • @android:id/background 进度条的背景。
  • @android:id/progress 这个玩意是进度条。
  • @android:id/secondaryProgress 缓冲进度。

借用一张图(上面blog中tou的,感觉很完美的契合了):

通过这张图,我们就非常直观的了解到了。整个seekbar 的绘制元素。

最后就是设置thumb,这个肯定不能是SVG。thumb 也有样式。

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 按下状态 -->
    <item android:drawable="@drawable/shape_seekbar_btn" android:state_pressed="true" />
​
    <!-- 焦点状态 -->
    <item android:drawable="@drawable/shape_seekbar_btn" android:state_focused="true" />
​
    <!-- 选择状态 -->
    <item android:drawable="@drawable/shape_seekbar_btn" android:state_selected="true" />
​
    <!-- 默认状态 -->
    <item android:drawable="@drawable/shape_seekbar_btn" />
</selector>

OK,这么一套下来。剩下的就是监听seek,然后设置文本了。

基于继承AppCompatSeekBar的自定义

因为某些原因(不知道到thumb不能设置svg,至于为啥不能,还没有细看),当时搞切图的时候,把thumb导成svg了,做的时候又发现搞切图的平台打不开了。算了,反正都需要自定义,那就thumb 我也自己画,反正设置的svg 不显示。

绘制thumb和文本

我们需求很简单,对thumb也没有啥状态,就一直那个样式。即然我都导svg了,这path我非用不可了好吧。我们通过:

arduino 复制代码
 PathParser.createPathFromPathData("path")

这么就获取到了一个path对象。有一个问题,那就是path 对象创建成功后,就没法设置开始位置了,我们thumb总不能一直卡在某个角落吧,但是,山不转水转,我canvas自己动不行吗?

  • canvas.translate() 平移
  • Matrix().postTranslate()也可以平移,canvas.setMatrix()

移动canvas有一个好处,那就是绘制文本的时候,不需要计算文本在x 轴的位置了,thumb绘制的时候已经平移了,一箭双雕,完美。剩下的就简单了,通过canvas.drawPath()和drawText() 即可。

绘制圆角矩形

当thumb 自己画的时候,已经走远了好吧。不同的手机跑出来thumb和进度条没有一个水平线上。OK,为了技术(填坑),进度和背景我也自己画。圆角矩形的path:

scss 复制代码
val path by lazy {
    Path().apply {
        val rectF = RectF(
            0f,
            0f,
            width ,
            height 
        )
        val radius = SizeUtils.dp2px(8f).toFloat()
        addRoundRect(
            rectF,
            radius, radius,
            Path.Direction.CW
        )
    }
}

seekbar 的进度和背景的区域就在rectf 中的right知不一样,但是不能用by lazy.所以通过函数返回即可。即然都自己画了,所以onDraw 中的supper就不需要了。

设置监听

这个就很简单了,就是在setOnSeekBarChangeListener于onProgressChanged函数中,调用invalidate()刷新绘制即可。

基于view自定义

我们上面基于seekbar 已经处理了绘制相关的逻辑了,基于view的自定义基本上就是基于onTouchEvent 分发event事件了。

  • ACTION_DOWN 按下的时候,如果需求上是可以点击切换的的话,就不拦截,点哪里然后通过x或者y计算一个进度值,如果不支持点击切换,那么需要判断触摸区域是否是thumb所在区域。
  • ACTION_MOVE 移动也是一个道理,每次移动一定的量的时候触发一次刷新,或者每次移动都重新计算进度刷新。
  • ACTION_UP 抬起的时候,也更新进度,当然可以更新。

总结

整体来说,还是蛮简单的,当然留下了一个坑为什么VectorDrawable 通过.draw(canvas) 绘制不出来还没有看,同时canvas 绘制 svg的bitmap 和drawable 好像都不行。

作为2024年第一篇水文,每天留一点坑,年终总结的时候就会发现要填的太多了。

相关推荐
双鱼大猫17 分钟前
一句话说透Android里面的ServiceManager的注册服务
android
双鱼大猫1 小时前
一句话说透Android里面的Window的内部机制
android
双鱼大猫2 小时前
一句话说透Android里面的为什么要设计Window?
android
双鱼大猫2 小时前
一句话说透Android里面的主线程创建时机,frameworks层面分析
android
苏金标2 小时前
android 快速定位当前页面
android
雾里看山5 小时前
【MySQL】内置函数
android·数据库·mysql
风浅月明6 小时前
[Android]页面间传递model列表
android
法迪6 小时前
Android自带的省电模式主要做什么呢?
android·功耗
风浅月明6 小时前
[Android]AppCompatEditText限制最多只能输入两位小数
android
没有晚不了安6 小时前
1.11作业
android