Android 滑動條、Slider径缅、Seekbar深度自定義

banner1.png

為了更好的滿足日常開發(fā)中對Slider控件的各種需要掺栅,以下我們來看下基于nifty-slider來定制我們所需的各種功能及交互效果

一、 功能支持

  • 支持滑動條起始值結(jié)束值的自定義

  • 支持滑動條指定步長以實現(xiàn)類似刻度的功能

  • 支持對滑塊的自定義以添加光環(huán)效果纳猪、滑塊形狀氧卧,滑塊投影、滑塊邊框氏堤、滑塊內(nèi)文本等定義

  • 支持使用任意圖像對滑塊進行修改

  • 支持對滑軌的起始結(jié)束位置添加圖標(biāo)或文本

  • 滑塊支持使用Lottie Animation

  • 支持滑動過程對滑塊沙绝、滑軌的狀態(tài)顏色高度等屬性添加交互動畫

  • 支持對控件的各個零部件進行深度的定制

二、 具體效果實現(xiàn)


1. Material Design 3 樣式

p1

此樣式只需要定義好滑塊鼠锈、滑軌的狀態(tài)顏色即可

<com.litao.slider.NiftySlider
        android:id="@+id/nifty_slider"
        android:layout_width="match_parent"
        android:layout_height="148dp"
        android:padding="16dp"
        android:value="50"
        android:valueFrom="0"
        android:valueTo="100"
        app:trackColor="@color/m3_demo_track_color"
        app:trackColorInactive="@color/m3_demo_track_inactive_color"
        app:thumbColor="@color/m3_demo_thumb_color"
        app:thumbShadowColor="@color/white"
        app:haloColor="@color/m3_demo_halo_color"/>

2. 微信閱讀中使用的Slider樣式

p2

此樣式我們需要使用到一個自定義效果ITEffect,定義好相關(guān)屬性后闪檬,然后給我們的Slider添加此效果即可

val customEffect = ITEffect(this).apply {
    startText = "大"
    endText = "小"
    startTextSize = 12f.dp
    endTextSize = 12f.dp
    startTintList = ColorStateList.valueOf(iconTintColor)
    endTintList = ColorStateList.valueOf(iconTintColor)
    startPadding = 12.dp
    endPadding = 12.dp
}


niftySlider3.apply {
    effect = customEffect
    setTrackTintList(ColorStateList.valueOf(activeTrackColor))
    setTrackInactiveTintList(ColorStateList.valueOf(inactiveTrackColor))
}

要記得添加thumbWithinTrackBounds=ture屬性,以保證我們的滑塊在滑軌內(nèi)部购笆,默認(rèn)情況是以滑塊中心為基準(zhǔn)點粗悯,滑動到起始和結(jié)束位置時滑塊會超出滑軌

<com.litao.slider.NiftySlider
        ...
        android:value="22"
        android:valueFrom="16"
        android:valueTo="28"
        app:trackHeight="36dp"
        app:thumbRadius="18dp"
        app:thumbTextSize="12sp"
        app:thumbText="邊距"
        android:hapticFeedbackEnabled="true"
        app:thumbTextColor="@color/we_read_theme_color"
        app:thumbColor="@color/we_read_thumb_color"
        android:stepSize="1"
        app:thumbWithinTrackBounds="true"
        app:enableDrawHalo="false" />

3. 自定義滑塊樣式

p3

這個只需要直接指定我們想要的圖像Res ID即可,像下面這樣,比較容易吧同欠。

setThumbCustomDrawable(R.drawable.custom_thumb)

如果普通的圖像滿足不了的話我們還可以自己去實現(xiàn)Drawable來完成有著更為豐富的交互和效果的滑塊样傍,像下面我們完成了一個嗶哩嗶哩視頻拖動條的效果,和上面相同只需要只需要調(diào)用setThumbCustomDrawable(myCustomDrawable)即可,可以看看到滑軌在滑動開始和結(jié)束后還有一個動畫效果铺遂,后面我們再詳細(xì)說明這部分

可以在 這里查看 BiliBiliDrawable的完整代碼

p4

4. 顏色選擇器

p5

我們可以使用ColorPickEffect來實現(xiàn)一個顏色選擇器衫哥,所選擇的顏色會在OnColorValueChangeListener回調(diào)中返回,然后對所需要的位置直接修改即可襟锐,如果默認(rèn)的色值無法滿足也可以調(diào)用ColorPickEffect.updateColors方法來修改為我們想要的顏色數(shù)組


val colorEffect = ColorPickEffect(niftySlider)

colorEffect.colorValueChangeListener =
    ColorPickEffect.OnColorValueChangeListener { slider, color, fromUser ->
        //color changed
        colorText.setBackgroundColor(color)
        colorText.text = Utils.toHexColorString(color)

        niftySlider.setThumbShadowColor(color)
        niftySlider.setThumbStrokeColor(ColorStateList.valueOf(color))
    }

5. 抖音視頻滑動條樣式

p6

可以看到抖音的滑動條中是在滑動開始和結(jié)束有一個很自然的動畫的過度炕檩,這個效果我們也可以借助AnimationEffect來完成,定義好我們自己的動畫對象,添加開始與結(jié)束的相關(guān)屬性配置即可笛质。在上面提到的嗶哩嗶哩的效果中我們也同時結(jié)合使用了該效果泉沾。

val animEffect = AnimationEffect(niftySlider).apply {
    srcTrackHeight = 3.dp
    srcThumbHeight = 6.dp
    srcThumbWidth = 6.dp
    srcThumbRadius = 3.dp
    srcThumbColor = thumbColor
    srcTrackColor = thumbTrackColor
    srcInactiveTrackColor = thumbInactiveColor

    targetTrackHeight = 12.dp
    targetThumbHeight = 16.dp
    targetThumbWidth = 8.dp
    targetThumbRadius = 5.dp
    targetThumbColor = Color.WHITE
    targetTrackColor = ColorUtils.setAlphaComponent(Color.WHITE, 0xDD)
    targetInactiveTrackColor = ColorUtils.setAlphaComponent(Color.WHITE, 0x33)

    animationListener = object : AnimationEffect.OnAnimationChangeListener {
        override fun onEnd(slider: NiftySlider) {
            //do something on animation end
        }
    }

    setInterpolator(FastOutLinearInInterpolator())
}

三、 定義我們自己的交互效果

從項目中可以看到包含了兩個模塊

  • nifty-slider : 滑動條的基礎(chǔ)功能
  • nifty-slider-effect : 用于深度定制滑動條妇押、增強交互效果
  1. 使用nifty-slider-effect lib 繼承 BaseEffect
  2. 實現(xiàn)相關(guān)方法跷究,開始我們的自定義之旅
    /** Called when a slider's touch event is being started */
    fun onStartTacking(slider: T)

    /** Called when a slider's touch event is being stopped */
    fun onStopTacking(slider: T)

    /** Called when the value of the slider changes  */
    fun onValueChanged(slider: T, value: Float, fromUser: Boolean)

    /** Called before draw inactive track . Return true if the interrupt default draw*/
    fun dispatchDrawInactiveTrackBefore(slider: T, canvas: Canvas, trackRect: RectF, yCenter: Float): Boolean
    /** Called after draw inactive track */
    fun drawInactiveTrackAfter(slider: T, canvas: Canvas, trackRect: RectF, yCenter: Float)

    /** Called before draw active track . Return true if the interrupt default draw*/
    fun dispatchDrawTrackBefore(slider: T, canvas: Canvas, trackRect: RectF, yCenter: Float): Boolean
    /** Called after draw active track */
    fun drawTrackAfter(slider: T, canvas: Canvas, trackRect: RectF, yCenter: Float)

    /** Called before draw thumb drawable . Return true if the interrupt default draw*/
    fun dispatchDrawThumbBefore(slider: T, canvas: Canvas, cx: Float, cy: Float): Boolean
    /** Called after draw thumb drawable */
    fun drawThumbAfter(slider: T, canvas: Canvas, cx: Float, cy: Float)
  1. 挑選合適的方法,例如dispatchDrawTrackBefore是在繪制激活狀態(tài)的滑軌之前調(diào)用敲霍,返回true表示由我們來接管繪制俊马,需要控件再進行此部件的繪制
  2. 下面我們結(jié)合Lottie Animation來定制一個有動畫效果的滑塊,首先引入lottie最新版本肩杈,下面我們需要用到其中的LottieDrawable
 implementation 'com.airbnb.android:lottie:6.0.0'

5.完整的效果代碼

class LottieAnimationEffect(private val slider: NiftySlider) : BaseEffect() {

    var animDrawable: LottieDrawable

    private var isAutoLoopMode = false


    init {
        slider.valueFrom = 0f
        slider.valueTo = 1f


        animDrawable = LottieDrawable().apply {
            enableMergePathsForKitKatAndAbove(true)
            callback = slider
            repeatCount = LottieDrawable.INFINITE
            setMinAndMaxProgress(0f,1f)
            addAnimatorUpdateListener {
                slider.invalidate()
            }
            progress = slider.value
        }

        slider.setThumbCustomDrawable(animDrawable)
    }


    override fun onValueChanged(slider: NiftySlider, value: Float, fromUser: Boolean) {
        super.onValueChanged(slider, value, fromUser)
        if (!isAutoLoopMode) {
            animDrawable.progress = value
        }
    }


    fun setAnimation(assetName: String) {
        val result: LottieResult<LottieComposition> =
            LottieCompositionFactory.fromAssetSync(slider.context.applicationContext, assetName)
        animDrawable.composition = result.value
    }


    fun setAutoLoopMode(isLoop: Boolean){
        if (isLoop == isAutoLoopMode){
            return
        }

        this.isAutoLoopMode = isLoop

        if (isLoop){
            animDrawable.start()
        }else{
            animDrawable.stop()
            animDrawable.progress = slider.value
        }
    }
}

6.這樣就完成了一個簡單的自定義效果柴我,我們來看下效果。


p7

四扩然、 Demo 下載

Demo APK 下載

五艘儒、 結(jié)束

希望使用這一個控件能夠滿足你項目中對slider的所有要求,滑動浮窗夫偶、區(qū)間選擇等功能還在開發(fā)中界睁,希望后續(xù)能夠提供更全面的更細(xì)致的方法及回調(diào)來滿足你的定制需求。我也會不斷的添加各種交互效果盡量涵蓋當(dāng)前所有主流應(yīng)用中的效果兵拢。

如當(dāng)前無法滿足你的需求可以提交 Issues
如你自定義了一個很棒的效果也可以提交PR

如果覺得有幫助就送上一個Star吧,為作者提供更多動力

項目文檔:查看

完整項目地址:查看

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末翻斟,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子说铃,更是在濱河造成了極大的恐慌访惜,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,651評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件腻扇,死亡現(xiàn)場離奇詭異债热,居然都是意外死亡,警方通過查閱死者的電腦和手機衙解,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來焰枢,“玉大人蚓峦,你說我怎么就攤上這事〖贸” “怎么了暑椰?”我有些...
    開封第一講書人閱讀 162,931評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長荐绝。 經(jīng)常有香客問我一汽,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,218評論 1 292
  • 正文 為了忘掉前任召夹,我火速辦了婚禮岩喷,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘监憎。我一直安慰自己纱意,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,234評論 6 388
  • 文/花漫 我一把揭開白布鲸阔。 她就那樣靜靜地躺著偷霉,像睡著了一般。 火紅的嫁衣襯著肌膚如雪褐筛。 梳的紋絲不亂的頭發(fā)上类少,一...
    開封第一講書人閱讀 51,198評論 1 299
  • 那天,我揣著相機與錄音渔扎,去河邊找鬼硫狞。 笑死,一個胖子當(dāng)著我的面吹牛赞警,可吹牛的內(nèi)容都是我干的妓忍。 我是一名探鬼主播,決...
    沈念sama閱讀 40,084評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼愧旦,長吁一口氣:“原來是場噩夢啊……” “哼世剖!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起笤虫,我...
    開封第一講書人閱讀 38,926評論 0 274
  • 序言:老撾萬榮一對情侶失蹤旁瘫,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后琼蚯,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體酬凳,經(jīng)...
    沈念sama閱讀 45,341評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,563評論 2 333
  • 正文 我和宋清朗相戀三年遭庶,在試婚紗的時候發(fā)現(xiàn)自己被綠了宁仔。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,731評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡峦睡,死狀恐怖翎苫,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情榨了,我是刑警寧澤煎谍,帶...
    沈念sama閱讀 35,430評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站龙屉,受9級特大地震影響呐粘,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,036評論 3 326
  • 文/蒙蒙 一作岖、第九天 我趴在偏房一處隱蔽的房頂上張望唆垃。 院中可真熱鬧,春花似錦鳍咱、人聲如沸降盹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蓄坏。三九已至,卻和暖如春丑念,著一層夾襖步出監(jiān)牢的瞬間涡戳,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評論 1 269
  • 我被黑心中介騙來泰國打工脯倚, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留渔彰,地道東北人。 一個月前我還...
    沈念sama閱讀 47,743評論 2 368
  • 正文 我出身青樓推正,卻偏偏與公主長得像恍涂,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子植榕,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,629評論 2 354

推薦閱讀更多精彩內(nèi)容