Android13 SeekBar使用教学。

写在前面:SeekBar就是我们常见的音量条、亮度条、各种可调节的进度条View,SeekBar默认的样子大多数公司不会用,感觉不够好看,这篇文章说一下SeekBar怎么用以及怎么自定义外观。老规矩,文末会贴出一个Demo APP的GitHub链接供大家学习使用,最后实现一个类似下图的亮度条,支持遥控器、手指滑动控制。
在这里插入图片描述

  下面我们按照这个思路依次介绍:引入SeekBar看看原生的样子——>自定义SeekBar的样式——>修改SeekBar获取焦点的样子。

第一步:layout引入 SeekBar

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_gravity="center"
    tools:context=".MainActivity">

    <SeekBar
        android:id="@+id/brightnessSeekBar"
        android:layout_width="190dp"
        android:layout_height="20dp"
        android:clickable="true"
        android:focusable="true"
        android:focusableInTouchMode="false"
        android:max="100"
        android:paddingStart="0dp"
        android:paddingEnd="0dp"
        android:progress="50"
        android:contentDescription="Adjust the volume"
        tools:ignore="MissingConstraints" />

</FrameLayout>

  解释下上面xml最关键的两个标签:android:max=“100” 进度条最大值,android:progress="50"进度条初始值。编译运行到设备上查看下原生的样子:
在这里插入图片描述
  解析下里面的要素:
在这里插入图片描述
  选中滑块左右拉动即可调节进度条。
  需要说明的是,SeekBar原生就支持遥控器控制,这块不用自己写,把焦点放到进度条上即可通过遥控器左右键控制。SeekBar的焦点默认落在滑块上,那怎么让焦点落在整个进度条上呢?这里我们埋个伏笔,后面再说。
在这里插入图片描述

第二步:自定义SeekBar的样子

  原生的样子我们看到了,其实也还行,但是你的UI设计师和老板肯定会觉得丑的,所以我们看看怎么个性化设置SeekBar。下面以设计一个这样的亮度条为例子说明:
在这里插入图片描述

  xml修改成这样:

    <SeekBar
        android:id="@+id/brightnessSeekBar"
        android:layout_width="190dp"
        android:layout_height="20dp"
        android:clickable="true"
        android:focusable="true"
        android:focusableInTouchMode="false"
        android:max="100"
        android:paddingStart="0dp"
        android:paddingEnd="0dp"
        android:progress="50"
        android:layout_gravity="center"
        android:progressDrawable="@drawable/custom_brightness_seekbar"
        android:contentDescription="Adjust the volume"
        tools:ignore="MissingConstraints" />

  android:progressDrawable 就是用来自定义进度条样子的标签。里面的custom_brightness_seekbar 需要自己创建:
在这里插入图片描述

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">



    <!-- 背景层 -->
    <item android:id="@android:id/background">
        <shape>
            <corners android:radius="3dp" />
            <solid android:color="#8005051C" />
        </shape>
    </item>


    <!-- 进度层 -->
    <item android:id="@android:id/progress">
        <inset
            android:insetLeft="2dp"
            android:insetRight="2dp"
            android:insetTop="2dp"
            android:insetBottom="2dp">
            <clip>
                <shape>
                    <corners android:radius="3dp" />
                    <solid android:color="#B3EBEEFF" />
                </shape>
            </clip>
        </inset>
    </item>

</layer-list>

  介绍一下custom_brightness_seekbar中的关键要素:id/background 是进度条的背景,id/progress是进度条。
在这里插入图片描述
  改完之后,变成下面这个样子:
在这里插入图片描述
  中间的滑块不想要,xml添加 android:thumb=“@null”
在这里插入图片描述
  下面就是最关键的地方,亮度和进度条百分比怎么加上去呢 这里我说下我一开始的思路,我当时想都自定义SeekBar了,能不能直接在SeekBar的背景里,左边加上一个ImageView亮度图标,右边加上一个进度条百分比TextView呢。我这么想也就这么做了,结果就是根本不行,浪费时间。Android就是这样,封装好的东西,你想多改一点,简直比登天还难。
  这里我写下一句至理名言:我们不管做任何需求,先给自己两个小时去做,如果两个小时毫无头绪,越做越乱,越来越没自信,那么听我的赶紧停下来,换个思路,换个方法。记住:方向不对,努力肯定白费,努力毫无意义!
  这里其实要用Android里的“图层叠加”的特性来解决。我们有时候是不是因为没有调整好布局,导致几个不同的View叠加在一起??OK,这里我们就是需要这种效果,layout改成下面这样:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <FrameLayout
        android:layout_width="wrap_content"
        android:layout_gravity="center"
        android:layout_height="wrap_content">
    <SeekBar
        android:id="@+id/brightnessSeekBar"
        android:layout_width="190dp"
        android:layout_height="20dp"
        android:clickable="true"
        android:focusable="true"
        android:focusableInTouchMode="false"
        android:max="100"
        android:paddingStart="0dp"
        android:paddingEnd="0dp"
        android:progress="50"
        android:layout_gravity="center"
        android:progressDrawable="@drawable/custom_brightness_seekbar"
        android:contentDescription="Adjust the volume"
        android:thumb="@null"
        tools:ignore="MissingConstraints" />

    <ImageView
        android:layout_width="12dp"
        android:layout_height="12dp"
        android:layout_gravity="left|center"
        android:layout_marginLeft="4dp"
        android:src="@drawable/quick_settings_brightness">

    </ImageView>

    <TextView
        android:layout_width="20dp"
        android:layout_height="20dp"
        android:layout_gravity="right"
        android:layout_marginRight="4dp"
        android:gravity="center"
        android:text="50%"
        android:textColor="@color/white"
        android:textSize="20px">

    </TextView>

</FrameLayout>

</FrameLayout>

  改完变成下面的样子:
  
  搞出来已经和我们想要的一样了。注意:可能会有同学感觉这样的方法投机取巧,有点Low。我个人是这样看的,技术上我们肯定是要追求高技术的,但是如果只有这种思维,往往很多时候我们会把事情想复杂,我的理解是,我们开发工程师要做一个“能快速满足需求,快速解决问题的人”,而不是“因为追求高技术性而卡在一个问题很久,或者写的高技术代码、实现的高技术方式有一堆BUG”。所以我的建议是,工作中先满足需求、积累经验,工作外不断提高技术理解,不断尝试新的解耦框架,这才是一个对的正反馈提高方式,别被蒙蔽了双眼,少年。

第三步:修改SeekBar默认获取焦点的样子

  Android13 View默认获取焦点的样子,一般是在整个View上面套一层灰黑色透明罩,类似下图:
在这里插入图片描述
  但是,SeekBar有个与众不同的特点,它的焦点是落在滑块上的,如果你司需求不需要滑块,同时要支持遥控器控制和手动滑动控制,而且亮度条的颜色还偏暗色,滑块上的焦点根本看不清,用户难以分辨,使用体验很差,这个时候就Ga住了,简直BUFF叠满。很不幸我们这种思路搞出来的亮度条,获取焦点的样子如下:
在这里插入图片描述

  中间有个透明小圈,而且还不能随着进度条的移动而移动,BUG住了。怎么才能改成焦点覆盖住整个进度条呢?写Android APP 就是和View打交道 ,如果有搞不定的东西,一定别忘了还有“自定义View”这个大杀器。自定义SeekBar如下:

package com.color.notification.view;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.widget.SeekBar;

public class CustomSeekBar extends androidx.appcompat.widget.AppCompatSeekBar {
    
    

    private Paint maskPaint;
    private boolean isSelected = false;

    public CustomSeekBar(Context context) {
    
    
        super(context);
        init();
    }

    public CustomSeekBar(Context context, AttributeSet attrs) {
    
    
        super(context, attrs);
        init();
    }

    public CustomSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
    
    
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
    
    
        maskPaint = new Paint();
        // 设置遮罩层颜色为激活状态的颜色
        maskPaint.setColor(Color.argb(80, 200, 200, 200));
    }

    private int getActivatedColor() {
    
    
        int[] attrs = new int[]{
    
    android.R.attr.colorActivatedHighlight};
        int colorResId = 0;

        if (getContext().getTheme().resolveAttribute(android.R.attr.colorActivatedHighlight, new android.util.TypedValue(), true)) {
    
    
            colorResId = getContext().getTheme().obtainStyledAttributes(new android.util.TypedValue().data, attrs).getResourceId(0, 0);
        }

        return getResources().getColor(colorResId);
    }

    @Override
    protected void onFocusChanged(boolean gainFocus, int direction, android.graphics.Rect previouslyFocusedRect) {
    
    
        super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);

        isSelected = gainFocus;
        invalidate(); // 重新绘制SeekBar
    }

    @Override
    protected synchronized void onDraw(Canvas canvas) {
    
    
        super.onDraw(canvas);

        if (isSelected) {
    
    
            // 绘制遮罩层
            canvas.drawRect(0, 0, getWidth(), getHeight(), maskPaint);
        }
    }
}

  上述代码的意思就是,每当进度条获取到焦点时,就在整个SeekBar的上层画一个灰黑色的透明遮罩层。代码不是很难,注释很少,读者一个方法一个方法的接着看,能看懂的。加上自定义View之后变成下面的样子:
在这里插入图片描述
  获取焦点时整个进度条都绘制了一个灰黑色头面遮罩层,但是滑块虽然没了,默认的焦点阴影效果还在,怎么去除呢?很简单,把进度条背景设置为透明即可:android:background=“@android:color/transparent” 。最终得到了理想的效果。

Demo APP Github链接:
https://github.com/xuhao120833/SeekBar/tree/master

写在最后:SeekBar其实还有一个非常经典的应用,就是视频播放、音乐播放、某雷下载、某盘下载等的加载进度条,他们用的SeekBar除了进度条、背景、滑块之外,还多了一个夹层,就是已经加载了多少内容的已加载内容条,如下所示对比图:至于中间的这个夹层叫什么名字,怎么去用,就靠各位读者去思考探索了,掌握了就是你自己的。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43522377/article/details/135290985
今日推荐