SeekBar 滑动验证效果

一、说明

  笔记主要是记录一些本人在开发当中的学习和使用笔记。笔记内容包含一些本人觉得重要的知识点、本人易犯的错误等。
  由于本人水平有限,其中出现的错误或者不合理的地方望各位读者多多包含,并指出其中不合理和错误的地方,以便我来修改正。谢谢!

二、笔记时间

  2019年06月27日:首次编辑
  2019年10月23日:第一次修改

三、简述

  本文主要讲述如何把 SeekBar 变成滑动验证的控件。

四、详情

  由于工作和生活的原因,很长一段时间没有写博客了,最近稍闲一点点,决定把这段时间工作中遇到的一些问题和解决方案记录下来。供自己和有需要的朋友借鉴。

  SeekBar 是我们工作当中经常使用到的控件,SeekBar 在画板中可以用他来调节画笔、画布的大小;可以用来调节图片颜色、显示下载进度;还可以制作滑动验证条等等。总的来说有很多场景我们都可以用SeekBar来实现。今天主要讲我的用 SeekBar 做滑动验证条的实现方式。

1、自定义 SeekBar 样式

  要实现美工小姐姐设计图的效果,以便与美工小姐姐产生共鸣,我们无法避免对SeekBar的样子进行自定义。下面介绍几个 SeekBar 的常用属性:

  • android:thumb //滑块样式
  • android:progressDrawable //进度条样式
  • android:max //拖动条的最大值
  • android:min //拖动条的最小值
  • android:progress //当前的进度值
  • android:thumbOffset //滑块偏移量
  • android:splitTrack //是否拆分绘制(滑块透明区域透明)
  • android:paddingStart //盒子内左边距
  • android:paddingEnd //盒子内右边距

  上面对几个重要属性进行了简短说明,下面一一说明怎么通过设置以上属性实现滑动验证效果。

1.1 android:thumb

  设置 thumb 可以实现自定义滑块样式。我们可以使用美工提供的图片,也可以用 shape 等来自定义滑块样式。我这里为了在不同机型上的通用性,是使用 shape 来自定义的样式,如下:




    
    

    


  样式效果是四角为圆角、颜色渐变、固定大小的正方形滑块。效果如下图:


thumb

1.2 android:progressDrawable

  设置 progressDrawable 可以实现自定义进度条样式。和 thumb 不一样的是,我们可以使用美工提供的图片,但是还是要用 layer-list 来进行组合,因为进度条有选中未选择等状态;当然也可以使用 shape 自定义。同样我这里也是使用 shape 自定义的,具体代码如下:




    
        
            
            
        
    

    
        
            
                
                
            
        
    

    
        
            
                
                
            
        
    

  先简要说明一下我自定义的效果,我实现的效果是选中状态为:未选中(滑块右侧)透明,选中和过渡区域为固定色(滑块渐变的开始颜色)。效果如下图:


progressDrawable

  细心的同学回发现里面有三个 @android 的 ID,那个这几个 ID到底是做什么用的勒,下面对他们说明一下。

  • @android:id/background //这个不难理解,从命名上我们就可以看出来,他是设置进度条的背景
  • @android:id/secondaryProgress //这个咋一看难以从命名上直接看出来,其实他是第二进度选中样式,和 android:secondaryProgress 一起看就不难理解了。
  • @android:id/progress //这个自然就是第一进度选中样式了。

1.3 android:max、android:min

  这两个属性就不需要多讲了,相信大家都明白,他就是设置进度条的最大、最小进度值。

1.4 android:progress

  这个属性应该大家也都明白,就是设置当前选中的进度值。当然还有 android:secondaryProgress 这个属性,这个属性就是设置第二进度的角度值。

1.5 android:thumbOffset

  这个属性从命名可以看出是设置滑块的偏移量,但是设置不同的值是什么效果勒?下面我们来看看设置为10dp、0dp、-10dp 的效果:

  • android:thumbOffset="10dp" //向左偏移
  • android:thumbOffset="0dp" //向右偏移一个滑块宽度
  • android:thumbOffset="-10dp" //向右偏移
10dp

0dp

-10dp

1.6 android:splitTrack

  这个属性还是很有用的,尤其是自定义滑块的时候。我自定义的滑块是圆角,当我没设置这个属性的时候(默认 android:splitTrack="true"),发现滑动的时候圆角处不是透明的,而是有一个白色的角,这明显不是我们想要的效果。
  出现这种不透明的现象我们就可以设置 android:splitTrack="false" ,这样就是透明的了。


splitTrack="true"

splitTrack="false"

1.6 android:paddingStart、android:paddingEnd

  我们知道固定 SeekBar 宽高之后,滑块左右都默认会偏移半个滑块的宽度,以便滑动到最左和最右的时候能够完整的显示滑块。其实这个偏移位置我们是可以自己设定的,就是通过 paddingStart、paddingEnd 来设置两边的偏移。当然 paddingLeft、paddingRight 也可以达到一样的效果。

1.7 滑动验证最终配置

  虽然上面介绍了那么多属性,不过这里实现滑动验证效果,我并没有全部使用,最终的配置如下:

  

  以上配置的效果如下图:


最终显示效果

2、滑动验证功能实现

  第一大点主要是自定义滑动条的样式,也就是实现我们美工小姐姐的奇思异想。剩下的滑动验证功能就需要我们这些攻城狮一句一句代码敲出来了!下面我介绍一下我的实现吧。

2.1 滑动停止回到初始位置

  这并不是什么复杂的功能,我们快速过。只需要给 SeekBar 设置 setOnSeekBarChangeListener 监听,然后实现监听,在监听中的 onStopTrackingTouch 方法里出现设置 progres 为 0 就好了。还是贴一下代码,如下:

    SeekBar seekBar = findViewById(R.id.seekbar);
    seekBar.setOnSeekBarChangeListener(this);

    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {
    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {
        seekBar.setProgress(0);
    }

2.1 屏蔽滑动条滑块外的点击事件

  原本以为做完以上工作,滑动验证就算完成了。可偏偏又出现了另外一个问题,说好的滑动验证,居然点击滑块的其它位置滑块也会设置过去。不过这是 SeekBar 的基本功能,我们不能说啥,现在我们看看怎么屏蔽滑块外的点击事件。我自定义了 SeekBar ,对触摸事件进行了处理,代码如下:

public class VerificationSeekBar extends AppCompatSeekBar {
    private boolean isInterception = true;

    public VerificationSeekBar(Context context) {
        super(context);
    }

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

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

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            isInterception = true;
            if (event.getX() > getThumb().getMinimumWidth()) {
                isInterception = false;
                return true;
            }
        }

        if (event.getAction() == MotionEvent.ACTION_MOVE && !isInterception) {
            return true;
        }

        return super.dispatchTouchEvent(event);
    }
}

  上面代码的逻辑也很简单,就是判断点击位置是否在滑块外,在滑块外就屏蔽啥也不做,但是消费掉滑动事件。
  现在替换 SeekBar 为我们自定义的 VerificationSeekBar ,就能够达到滑动验证的效果了。

2.2 解决点击滑动条尾部直接验证成功的问题

  我在做画板的时候,利用该方式来做滑动清屏,结果发现了一个隐藏bug。我们程序员往往最怕这种隐藏bug了,但是怕归怕,问题我们还是要解决了。当然了,这个bug并不是很难解。
  下面说一下这个具体的bug:在白板当中,我设置的是滑动到90%以上,松手即触发清屏。结果当我们点击滑动条末尾位置时,同样触发了清屏。说好的滑动清屏,可是实际使用结果却可以点击清屏,这很明显和我们的设计方案不符合。因此我做了以下小修改,来完善该功能。
  我把该问题记录下来,一个是给自己做笔记,另外一个我相信滑动验证也会有类似的问题,希望读者能够直接解决好问题。以下就是我的解决方案。

2.2.1 把 isInterception 的值提供出来

  把 isInterception 的值提供出来其实就是在 VerificationSeekBar 中添加一个获取该值的方法,具体如下:

// VerificationSeekBar.java 
/**
     * 获取是否滑动清屏
     * 
     * @return true:滑动验证    false:非滑动验证
     */
    public boolean isInterception() {
        return isInterception;
    }

2.2.2 判断是否是滑动验证

  这个就需要我们在实现SeekBar的监听事件时,利用 isInterception 方法来判断是否触发验证成功。具体如下:

    VerificationSeekBar mySeekBar;
    mySeekBar = findViewById(R.id.seekbar);
    mySeekBar.setOnSeekBarChangeListener(this);

    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {
    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {
      if (mySeekBar.isInterception()) {
            succeed();  //滑动验证成功
        } else {
            failed();  //滑动验证失败
        }
        seekBar.setProgress(0);
    }

2.2.3 其它解决方案

  我以上的解决方案并不是唯一的解决方案。我再提供两种解决思路,因为项目时间紧张我就没一一验证了。读者可以验证一下,把验证结果加到评论区,让所有读者共勉。

  • 第一种解决方案和我上面提供的解决方案一样,只是我们可以把 setOnSeekBarChangeListener 监听的逻辑在 VerificationSeekBar 中实现,并向外提供一个 succeed、failed 接口,来保证封装的完整性。本人推荐该方法。

  • 第二中解决方案,我们可以利用 onStartTrackingTouch ,通过开始点击的值(位置)来判断是否是滑动验证,非点击滑动条末尾,但是要增加变量,不建议使用。用我画板90%触发清屏为例,我们可以修改为如下:

    int startProgress = 0;

    SeekBar seekBar = findViewById(R.id.seekbar);
    seekBar.setOnSeekBarChangeListener(this);

    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {
        startProgress = seekBar.getProgress();
    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {
        if (startProgress < 90 && seekBar.getProgress() >= 90) {
            succeed();  //滑动验证成功
        } else {
            failed();  //滑动验证失败
        }
        seekBar.setProgress(0);
    }

注:第二中方案要着重验证,从滑动条中间拖到满足条件,是否会被判断为 succeed?若满足验证成功,建议和第一种犯案一样封装一下;若验证失败,建议把 <90 的条件改为,<= getThumb().getMinimumWidth()

你可能感兴趣的:(SeekBar 滑动验证效果)