SeekBar 滑動(dòng)驗(yàn)證效果

一、說(shuō)明

??筆記主要是記錄一些本人在開發(fā)當(dāng)中的學(xué)習(xí)和使用筆記掏愁。筆記內(nèi)容包含一些本人覺(jué)得重要的知識(shí)點(diǎn)歇由、本人易犯的錯(cuò)誤等。
??由于本人水平有限果港,其中出現(xiàn)的錯(cuò)誤或者不合理的地方望各位讀者多多包含沦泌,并指出其中不合理和錯(cuò)誤的地方,以便我來(lái)修改正辛掠。謝謝谢谦!

二释牺、筆記時(shí)間

??2019年06月27日:首次編輯
??2019年10月23日:第一次修改

三、簡(jiǎn)述

??本文主要講述如何把 SeekBar 變成滑動(dòng)驗(yàn)證的控件回挽。

四没咙、詳情

??由于工作和生活的原因,很長(zhǎng)一段時(shí)間沒(méi)有寫博客了千劈,最近稍閑一點(diǎn)點(diǎn)祭刚,決定把這段時(shí)間工作中遇到的一些問(wèn)題和解決方案記錄下來(lái)。供自己和有需要的朋友借鑒墙牌。

??SeekBar 是我們工作當(dāng)中經(jīng)常使用到的控件涡驮,SeekBar 在畫板中可以用他來(lái)調(diào)節(jié)畫筆、畫布的大秀竟拧遮怜;可以用來(lái)調(diào)節(jié)圖片顏色淋袖、顯示下載進(jìn)度鸿市;還可以制作滑動(dòng)驗(yàn)證條等等〖赐耄總的來(lái)說(shuō)有很多場(chǎng)景我們都可以用SeekBar來(lái)實(shí)現(xiàn)焰情。今天主要講我的用 SeekBar 做滑動(dòng)驗(yàn)證條的實(shí)現(xiàn)方式。

1剥懒、自定義 SeekBar 樣式

??要實(shí)現(xiàn)美工小姐姐設(shè)計(jì)圖的效果内舟,以便與美工小姐姐產(chǎn)生共鳴,我們無(wú)法避免對(duì)SeekBar的樣子進(jìn)行自定義初橘。下面介紹幾個(gè) SeekBar 的常用屬性:

  • android:thumb //滑塊樣式
  • android:progressDrawable //進(jìn)度條樣式
  • android:max //拖動(dòng)條的最大值
  • android:min //拖動(dòng)條的最小值
  • android:progress //當(dāng)前的進(jìn)度值
  • android:thumbOffset //滑塊偏移量
  • android:splitTrack //是否拆分繪制(滑塊透明區(qū)域透明)
  • android:paddingStart //盒子內(nèi)左邊距
  • android:paddingEnd //盒子內(nèi)右邊距

??上面對(duì)幾個(gè)重要屬性進(jìn)行了簡(jiǎn)短說(shuō)明验游,下面一一說(shuō)明怎么通過(guò)設(shè)置以上屬性實(shí)現(xiàn)滑動(dòng)驗(yàn)證效果。

1.1 android:thumb

??設(shè)置 thumb 可以實(shí)現(xiàn)自定義滑塊樣式保檐。我們可以使用美工提供的圖片耕蝉,也可以用 shape 等來(lái)自定義滑塊樣式。我這里為了在不同機(jī)型上的通用性夜只,是使用 shape 來(lái)自定義的樣式垒在,如下:

<!-- seekbar_thumb.xml -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">

    <size
        android:width="11dp"
        android:height="11dp" />
    <corners android:radius="3dp" />

    <gradient
        android:endColor="#FF44A3FF"
        android:startColor="#FF9CDCFF" />

</shape>

??樣式效果是四角為圓角、顏色漸變扔亥、固定大小的正方形滑塊场躯。效果如下圖:


thumb

1.2 android:progressDrawable

??設(shè)置 progressDrawable 可以實(shí)現(xiàn)自定義進(jìn)度條樣式。和 thumb 不一樣的是旅挤,我們可以使用美工提供的圖片踢关,但是還是要用 layer-list 來(lái)進(jìn)行組合,因?yàn)檫M(jìn)度條有選中未選擇等狀態(tài)粘茄;當(dāng)然也可以使用 shape 自定義耘成。同樣我這里也是使用 shape 自定義的,具體代碼如下:

<!-- seekbar_progress.xml -->
<?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:height="11dp"
        android:gravity="center_vertical">
        <shape>
            <corners android:radius="3dp" />
            <solid android:color="@android:color/transparent" />
        </shape>
    </item>

    <item
        android:id="@android:id/secondaryProgress"
        android:height="11dp"
        android:gravity="center_vertical">
        <clip>
            <shape>
                <corners android:radius="3dp" />
                <solid android:color="#FF9CDCFF" />
            </shape>
        </clip>
    </item>

    <item
        android:id="@android:id/progress"
        android:height="11dp"
        android:gravity="center_vertical">
        <clip>
            <shape>
                <corners android:radius="3dp" />
                <solid android:color="#FF9CDCFF" />
            </shape>
        </clip>
    </item>
</layer-list>

??先簡(jiǎn)要說(shuō)明一下我自定義的效果,我實(shí)現(xiàn)的效果是選中狀態(tài)為:未選中(滑塊右側(cè))透明瘪菌,選中和過(guò)渡區(qū)域?yàn)楣潭ㄉɑ瑝K漸變的開始顏色)撒会。效果如下圖:


progressDrawable

??細(xì)心的同學(xué)回發(fā)現(xiàn)里面有三個(gè) @android 的 ID,那個(gè)這幾個(gè) ID到底是做什么用的勒师妙,下面對(duì)他們說(shuō)明一下诵肛。

  • @android:id/background //這個(gè)不難理解,從命名上我們就可以看出來(lái)默穴,他是設(shè)置進(jìn)度條的背景
  • @android:id/secondaryProgress //這個(gè)咋一看難以從命名上直接看出來(lái)怔檩,其實(shí)他是第二進(jìn)度選中樣式,和 android:secondaryProgress 一起看就不難理解了蓄诽。
  • @android:id/progress //這個(gè)自然就是第一進(jìn)度選中樣式了薛训。

1.3 android:max、android:min

??這兩個(gè)屬性就不需要多講了仑氛,相信大家都明白乙埃,他就是設(shè)置進(jìn)度條的最大、最小進(jìn)度值锯岖。

1.4 android:progress

??這個(gè)屬性應(yīng)該大家也都明白介袜,就是設(shè)置當(dāng)前選中的進(jìn)度值。當(dāng)然還有 android:secondaryProgress 這個(gè)屬性出吹,這個(gè)屬性就是設(shè)置第二進(jìn)度的角度值遇伞。

1.5 android:thumbOffset

??這個(gè)屬性從命名可以看出是設(shè)置滑塊的偏移量,但是設(shè)置不同的值是什么效果勒捶牢?下面我們來(lái)看看設(shè)置為10dp鸠珠、0dp、-10dp 的效果:

  • android:thumbOffset="10dp" //向左偏移
  • android:thumbOffset="0dp" //向右偏移一個(gè)滑塊寬度
  • android:thumbOffset="-10dp" //向右偏移
10dp

0dp

-10dp

1.6 android:splitTrack

??這個(gè)屬性還是很有用的秋麸,尤其是自定義滑塊的時(shí)候渐排。我自定義的滑塊是圓角,當(dāng)我沒(méi)設(shè)置這個(gè)屬性的時(shí)候(默認(rèn) android:splitTrack="true")竹勉,發(fā)現(xiàn)滑動(dòng)的時(shí)候圓角處不是透明的飞盆,而是有一個(gè)白色的角,這明顯不是我們想要的效果次乓。
??出現(xiàn)這種不透明的現(xiàn)象我們就可以設(shè)置 android:splitTrack="false" 吓歇,這樣就是透明的了。


splitTrack="true"

splitTrack="false"

1.6 android:paddingStart票腰、android:paddingEnd

??我們知道固定 SeekBar 寬高之后城看,滑塊左右都默認(rèn)會(huì)偏移半個(gè)滑塊的寬度,以便滑動(dòng)到最左和最右的時(shí)候能夠完整的顯示滑塊杏慰。其實(shí)這個(gè)偏移位置我們是可以自己設(shè)定的测柠,就是通過(guò) paddingStart炼鞠、paddingEnd 來(lái)設(shè)置兩邊的偏移。當(dāng)然 paddingLeft轰胁、paddingRight 也可以達(dá)到一樣的效果谒主。

1.7 滑動(dòng)驗(yàn)證最終配置

??雖然上面介紹了那么多屬性,不過(guò)這里實(shí)現(xiàn)滑動(dòng)驗(yàn)證效果赃阀,我并沒(méi)有全部使用霎肯,最終的配置如下:

  <SeekBar
            android:id="@+id/seekbar"
            android:layout_width="50dp"
            android:layout_height="11dp"
            android:paddingStart="6dp"
            android:paddingEnd="6dp"
            android:progressDrawable="@drawable/seekbar_progress"
            android:splitTrack="false"
            android:thumb="@drawable/seekbar_thumb" />

??以上配置的效果如下圖:


最終顯示效果

2、滑動(dòng)驗(yàn)證功能實(shí)現(xiàn)

??第一大點(diǎn)主要是自定義滑動(dòng)條的樣式榛斯,也就是實(shí)現(xiàn)我們美工小姐姐的奇思異想观游。剩下的滑動(dòng)驗(yàn)證功能就需要我們這些攻城獅一句一句代碼敲出來(lái)了!下面我介紹一下我的實(shí)現(xiàn)吧驮俗。

2.1 滑動(dòng)停止回到初始位置

??這并不是什么復(fù)雜的功能懂缕,我們快速過(guò)。只需要給 SeekBar 設(shè)置 setOnSeekBarChangeListener 監(jiān)聽(tīng)王凑,然后實(shí)現(xiàn)監(jiān)聽(tīng)搪柑,在監(jiān)聽(tīng)中的 onStopTrackingTouch 方法里出現(xiàn)設(shè)置 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 屏蔽滑動(dòng)條滑塊外的點(diǎn)擊事件

??原本以為做完以上工作拌屏,滑動(dòng)驗(yàn)證就算完成了潮针∪踉簦可偏偏又出現(xiàn)了另外一個(gè)問(wèn)題衔憨,說(shuō)好的滑動(dòng)驗(yàn)證,居然點(diǎn)擊滑塊的其它位置滑塊也會(huì)設(shè)置過(guò)去。不過(guò)這是 SeekBar 的基本功能汪榔,我們不能說(shuō)啥,現(xiàn)在我們看看怎么屏蔽滑塊外的點(diǎn)擊事件仓蛆。我自定義了 SeekBar 睬涧,對(duì)觸摸事件進(jìn)行了處理,代碼如下:

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);
    }
}

??上面代碼的邏輯也很簡(jiǎn)單矗晃,就是判斷點(diǎn)擊位置是否在滑塊外仑嗅,在滑塊外就屏蔽啥也不做,但是消費(fèi)掉滑動(dòng)事件张症。
??現(xiàn)在替換 SeekBar 為我們自定義的 VerificationSeekBar 仓技,就能夠達(dá)到滑動(dòng)驗(yàn)證的效果了。

2.2 解決點(diǎn)擊滑動(dòng)條尾部直接驗(yàn)證成功的問(wèn)題

??我在做畫板的時(shí)候俗他,利用該方式來(lái)做滑動(dòng)清屏脖捻,結(jié)果發(fā)現(xiàn)了一個(gè)隱藏bug。我們程序員往往最怕這種隱藏bug了兆衅,但是怕歸怕地沮,問(wèn)題我們還是要解決了嗜浮。當(dāng)然了,這個(gè)bug并不是很難解摩疑。
??下面說(shuō)一下這個(gè)具體的bug:在白板當(dāng)中危融,我設(shè)置的是滑動(dòng)到90%以上,松手即觸發(fā)清屏雷袋。結(jié)果當(dāng)我們點(diǎn)擊滑動(dòng)條末尾位置時(shí)专挪,同樣觸發(fā)了清屏。說(shuō)好的滑動(dòng)清屏片排,可是實(shí)際使用結(jié)果卻可以點(diǎn)擊清屏寨腔,這很明顯和我們的設(shè)計(jì)方案不符合。因此我做了以下小修改率寡,來(lái)完善該功能迫卢。
??我把該問(wèn)題記錄下來(lái),一個(gè)是給自己做筆記冶共,另外一個(gè)我相信滑動(dòng)驗(yàn)證也會(huì)有類似的問(wèn)題乾蛤,希望讀者能夠直接解決好問(wèn)題。以下就是我的解決方案捅僵。

2.2.1 把 isInterception 的值提供出來(lái)

??把 isInterception 的值提供出來(lái)其實(shí)就是在 VerificationSeekBar 中添加一個(gè)獲取該值的方法家卖,具體如下:

// VerificationSeekBar.java 
/**
     * 獲取是否滑動(dòng)清屏
     * 
     * @return true:滑動(dòng)驗(yàn)證    false:非滑動(dòng)驗(yàn)證
     */
    public boolean isInterception() {
        return isInterception;
    }

2.2.2 判斷是否是滑動(dòng)驗(yàn)證

??這個(gè)就需要我們?cè)趯?shí)現(xiàn)SeekBar的監(jiān)聽(tīng)事件時(shí),利用 isInterception 方法來(lái)判斷是否觸發(fā)驗(yàn)證成功庙楚。具體如下:

    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();  //滑動(dòng)驗(yàn)證成功
        } else {
            failed();  //滑動(dòng)驗(yàn)證失敗
        }
        seekBar.setProgress(0);
    }

2.2.3 其它解決方案

??我以上的解決方案并不是唯一的解決方案上荡。我再提供兩種解決思路,因?yàn)轫?xiàng)目時(shí)間緊張我就沒(méi)一一驗(yàn)證了馒闷。讀者可以驗(yàn)證一下酪捡,把驗(yàn)證結(jié)果加到評(píng)論區(qū),讓所有讀者共勉纳账。

  • 第一種解決方案和我上面提供的解決方案一樣逛薇,只是我們可以把 setOnSeekBarChangeListener 監(jiān)聽(tīng)的邏輯在 VerificationSeekBar 中實(shí)現(xiàn),并向外提供一個(gè) succeed疏虫、failed 接口永罚,來(lái)保證封裝的完整性。本人推薦該方法卧秘。

  • 第二中解決方案呢袱,我們可以利用 onStartTrackingTouch ,通過(guò)開始點(diǎn)擊的值(位置)來(lái)判斷是否是滑動(dòng)驗(yàn)證斯议,非點(diǎn)擊滑動(dòng)條末尾产捞,但是要增加變量,不建議使用哼御。用我畫板90%觸發(fā)清屏為例坯临,我們可以修改為如下:

    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();  //滑動(dòng)驗(yàn)證成功
        } else {
            failed();  //滑動(dòng)驗(yàn)證失敗
        }
        seekBar.setProgress(0);
    }

注:第二中方案要著重驗(yàn)證焊唬,從滑動(dòng)條中間拖到滿足條件,是否會(huì)被判斷為 succeed看靠?若滿足驗(yàn)證成功赶促,建議和第一種犯案一樣封裝一下;若驗(yàn)證失敗挟炬,建議把 <90 的條件改為鸥滨,<= getThumb().getMinimumWidth()

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市谤祖,隨后出現(xiàn)的幾起案子婿滓,更是在濱河造成了極大的恐慌,老刑警劉巖粥喜,帶你破解...
    沈念sama閱讀 218,858評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件凸主,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡额湘,警方通過(guò)查閱死者的電腦和手機(jī)卿吐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)锋华,“玉大人嗡官,你說(shuō)我怎么就攤上這事√夯溃” “怎么了衍腥?”我有些...
    開封第一講書人閱讀 165,282評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)芥丧。 經(jīng)常有香客問(wèn)我紧阔,道長(zhǎng)坊罢,這世上最難降的妖魔是什么续担? 我笑而不...
    開封第一講書人閱讀 58,842評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮活孩,結(jié)果婚禮上物遇,老公的妹妹穿的比我還像新娘。我一直安慰自己憾儒,他們只是感情好询兴,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著起趾,像睡著了一般诗舰。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上训裆,一...
    開封第一講書人閱讀 51,679評(píng)論 1 305
  • 那天眶根,我揣著相機(jī)與錄音蜀铲,去河邊找鬼。 笑死属百,一個(gè)胖子當(dāng)著我的面吹牛记劝,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播族扰,決...
    沈念sama閱讀 40,406評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼厌丑,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了渔呵?” 一聲冷哼從身側(cè)響起怒竿,我...
    開封第一講書人閱讀 39,311評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎扩氢,沒(méi)想到半個(gè)月后愧口,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,767評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡类茂,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年耍属,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片巩检。...
    茶點(diǎn)故事閱讀 40,090評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡厚骗,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出兢哭,到底是詐尸還是另有隱情领舰,我是刑警寧澤,帶...
    沈念sama閱讀 35,785評(píng)論 5 346
  • 正文 年R本政府宣布迟螺,位于F島的核電站冲秽,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏矩父。R本人自食惡果不足惜锉桑,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望窍株。 院中可真熱鬧民轴,春花似錦、人聲如沸球订。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)冒滩。三九已至微驶,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間开睡,已是汗流浹背因苹。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工较店, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人容燕。 一個(gè)月前我還...
    沈念sama閱讀 48,298評(píng)論 3 372
  • 正文 我出身青樓梁呈,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親蘸秘。 傳聞我的和親對(duì)象是個(gè)殘疾皇子官卡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評(píng)論 2 355