07.10 控件-SeekBar

2022/4/4 Android 开发基础

SeekBar(拖动进度条,也简称:拖动条)是 ProgressBar 进度条的一个扩展。它增加了一个可拖动的拇指,用户可以触摸并向左或向右拖动来设置当前的进度级别。

拖动进度条最常用的地方就是音乐播放器或者视频播放器场景,通过滑动拖动进度条来进行音量控制或者播放进度的控制。一些应用的相关设置项如亮度,音量等等场景也是使用非常多的。

SeekBar 是 ProgressBar 的子类,所以 ProgressBar 的属性和特性都是可以使用的,增加了一个滑块的属性和可以实时监听滑动的进度值的特性。

# 基本属性

自己的属性:

  • android:thumb:指定滑块drawable资源

继承自 ProgressBar 的属性:

  • android:max:进度条的进度最大值,默认值100
  • android:min:进度条的进度最小值,默认值0
  • android:progress:进度条当前进度值
  • android:progressDrawable:设置进度轨道对应的Drawable对象
  • android:secondaryProgress:二级进度值,默认值0,多数用于标记参考进度

注意:继承属性中的不确定进度属性,在拖动进度条中没有任何意义,使用后将无法拖动进度。

# 获取和监听进度

获取进度可以通过 getProgress() 方法获取一级进度,getSecondaryProgress() 方法获取二级进度,拖动进度条中,二级进度一般用于标记一些重要的节点进度参考使用

可以通过设置 SeekBar.OnSeekBarChangeListener 来监听进度(一级进度)变化,有三个对应通知的方法:

  • onProgressChanged:进度发生改变时通知
  • onStartTrackingTouch:开始按住SeekBar时通知
  • onStopTrackingTouch:释放SeekBar时通知

注意:拖动进度条滑块操作的进度是一级进度,二级进度是继承自 ProgressBar 的,需要主动设置进度和获取,且进度条进度监听通知的也是一级进度变化。

# 基本用法示例

xml布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical">

    <!-- 拖动进度条,当前进度50,二级进度60,最大进度100,最小进度0 -->
    <SeekBar
        android:id="@+id/seekbar_demo"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="100"
        android:min="0"
        android:progress="50"
        android:secondaryProgress="60" />

</LinearLayout>

代码:

SeekBar seekBar = findViewById(R.id.seekbar_demo);
// 监听进度变化
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
        // 进度发生变化通知,progress:当前一级进度,fromUser:是否是用户滑动触发的
        Log.d(TAG, "onProgressChanged: progress = " + progress
                + ", secondaryProgress = " + seekBar.getSecondaryProgress()
                + ", fromUser = " + fromUser);
    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {
        // 当开始按住seekBar时通知
        Log.d(TAG, "onStartTrackingTouch: ");
    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {
        // 当释放seekBar时通知
        Log.d(TAG, "onStopTrackingTouch: ");
    }
});

// 获取当前的一级进度
int progress = seekBar.getProgress();
Log.d(TAG, "getProgress: progress = " + progress);

// 获取二级进度, 拖动条中使用场景较少,一般用于标记重要进度节点参考使用
int secondaryProgress = seekBar.getSecondaryProgress();
Log.d(TAG, "getSecondaryProgress: secondaryProgress = " + secondaryProgress);

// 设置一级进度为60,会有进度回调
seekBar.setProgress(60);

// 设置二级进度为80,没有进度回调
seekBar.setSecondaryProgress(80);

运行日志输出:

getProgress: progress = 50
getSecondaryProgress: secondaryProgress = 60
onProgressChanged: progress = 60, secondaryProgress = 60, fromUser = false
onStartTrackingTouch: 
onProgressChanged: progress = 59, secondaryProgress = 80, fromUser = true
onProgressChanged: progress = 58, secondaryProgress = 80, fromUser = true
onProgressChanged: progress = 57, secondaryProgress = 80, fromUser = true
onProgressChanged: progress = 56, secondaryProgress = 80, fromUser = true
onProgressChanged: progress = 55, secondaryProgress = 80, fromUser = true
onProgressChanged: progress = 54, secondaryProgress = 80, fromUser = true
onProgressChanged: progress = 53, secondaryProgress = 80, fromUser = true
onProgressChanged: progress = 54, secondaryProgress = 80, fromUser = true
onStopTrackingTouch: 

效果图:

SeekBar 默认效果图

# 自定义进度样式

系统默认的拖动进度条的样式是满足不了各种产品的 UI 设计的,所以就需要自定义样式的进度条,自定义样式进度条方式有很多,一般主要有两种,一种是自定义进度条的相关 drawable 资源来实现,还有一种是自定义 View 绘制的方式实现。

在这里我们主要进行前者自定义指定 drawable 资源方式实现,自定义 View 实现方式在后续会有相关详细的介绍。

可以自定义拖动进度条的背景二级进度一级进度和thumb滑块的资源来实现个性化样式,在这里就简单实现下,了解自定义的原理和方式,想要好看的效果还是需要专业的 UI 人员来设计配色方案的。

  1. 创建 thumb 滑块的相关 drawable 资源文件,可以使用 drawable shape 或者图片资源实现,这里使用前者来实现:

shape_seekbar_normal.xml:正常滑块样式

<?xml version="1.0" encoding="utf-8"?>
<!-- 滑块:正常状态形状样式 -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle"> <!-- 矩形 -->
    <!-- 大小 -->
    <size
        android:width="20dp"
        android:height="20dp" />

    <!-- 渐变色背景 -->
    <gradient
        android:angle="0"
        android:endColor="#2196F3"
        android:startColor="#FF5722" />

    <!-- 描边 -->
    <stroke
        android:width="4dp"
        android:color="#4CAF50" />
</shape>

shape_seekbar_press.xml:按压状态滑块样式

<?xml version="1.0" encoding="utf-8"?>
<!-- 滑块:按压状态形状样式 -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle"> <!-- 矩形 -->
    <!-- 大小 -->
    <size
        android:width="20dp"
        android:height="20dp" />

    <!-- 背景 -->
    <solid android:color="#FFFFFF" />

    <!-- 描边 -->
    <stroke
        android:width="4dp"
        android:color="#4CAF50" />

</shape>

selector_seekbar_thumb.xml:滑块状态选择器

<?xml version="1.0" encoding="utf-8"?>
<!-- thumb 滑块状态选择器 -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="false" android:drawable="@drawable/shape_seekbar_normal" />
    <item android:state_pressed="true" android:drawable="@drawable/shape_seekbar_press" />
</selector>
  1. 创建拖动进度条的样式 drawable 文件,自定义一个层级的 drawable 资源文件,并指定其对应资源的特定 id:

progress_seekbar_bg.xml:定义拖动进度条的三层显示的样式

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- 3层的顺序即为显示时的叠加层级 -->
    <!-- 第一层:背景资源,必须指定此id来区分:@android:id/background -->
    <item android:id="@android:id/background">
        <shape>
            <corners android:radius="5dip" />

            <solid android:color="#CCCCCC" />
        </shape>
    </item>

    <!--
    第二层:二级进度条的资源, 必须指定此id来区分:@android:id/secondaryProgress
    一般用于标记特殊进度位置
    -->
    <item android:id="@android:id/secondaryProgress">
        <clip>
            <shape>
                <corners android:radius="5dip" />
                <solid android:color="#99FF9800" />
            </shape>
        </clip>
    </item>

    <!-- 第三层:一级进度条的颜色,也可以直接替换成图片,必须指定此id来区分:@android:id/progress -->
    <item android:id="@android:id/progress">
        <clip>
            <shape>
                <corners android:radius="5dip" />
                <!-- 单色填充 -->
                <!--<solid android:color="#8BC34A" />-->
                <!-- 渐变色填充 -->
                <gradient
                    android:angle="0"
                    android:startColor="#A0D9F3"
                    android:endColor="#2196F3" />
            </shape>
        </clip>
    </item>

</layer-list>
  1. 使用创建的自定义样式资源

xml布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical">

    <!-- 拖动进度条,当前进度50,二级进度60,最大进度100,最小进度0 -->
    <SeekBar
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="100"
        android:min="0"
        android:progress="50"
        android:progressDrawable="@drawable/progress_seekbar_bg"
        android:secondaryProgress="60"
        android:thumb="@drawable/selector_seekbar_thumb" />

    <!-- 拖动进度条: 背景条填满控件大小,设置左右padding为0dp即可 -->
    <SeekBar
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:max="100"
        android:min="0"
        android:paddingStart="0dp"
        android:paddingLeft="0dp"
        android:paddingEnd="0dp"
        android:paddingRight="0dp"
        android:progress="50"
        android:progressDrawable="@drawable/progress_seekbar_bg"
        android:secondaryProgress="60"
        android:thumb="@drawable/selector_seekbar_thumb" />

</LinearLayout>

效果图:

SeekBar 自定义样式效果图

注意:SeekBar 默认背景条不会充满其控件显示,会预留滑块大小左右的内边距离,如需背景填满控件的大小,可以设置相应左右方向的 paddingXXX 大小为 0dp 即可,同时需要做好相应进度和显示的适配

# 结束

本节介绍了拖动进度条控件的常用属性和相关使用方法,并实现了自定义进度条样式。更多进度条的属性和用法请参考:SeekBar (opens new window)