Flutter Slider 組件隱藏刻度

Flutter 里的 Slider 組件類似 Android 里的 SeekBar 組件,中間有一個滑塊,可以滑動選擇進度。最近在使用 Slider 組件時確碰到一個問題,具體如下圖所示:


Slider帶有刻度

圖中可以看到,組件上面有一個個等分的點,剛開始還以為是什么屬性配置錯誤了,后來通過研究官方文檔以及源碼發(fā)現(xiàn),這叫tickMark,俗稱刻度。但是我只想要一個單純的滑動條,并不想要在上面顯示刻度,找了一圈發(fā)現(xiàn) Slider 并沒有屬性可以控制這個。

后來經(jīng)過一番查找,發(fā)現(xiàn)可以通過 SliderTheme 來改變 Slider 組件的一些默認屬性,里面恰好有 activeTickMarkColor、inactiveTickMarkColor、tickMarkShape是與tickMark相關(guān)的。于是想到 將 tickMarkColor 配置成透明色不就不顯示刻度了么,試驗了一下如下代碼:

  SliderTheme(
    data: SliderTheme.of(context).copyWith(
        activeTickMarkColor: Colors.transparent,
        inactiveTickMarkColor: Colors.transparent
      ),
    child: Slider(
        min: 1, max: 100, value: _value, divisions: 10, 
        activeColor: Colors.red,
        inactiveColor: Colors.grey,
        onChanged: (value) {
          setState(() {
            _value = value;
          });
        }));

結(jié)果很遺憾,一點效果都沒有(有知道原因的可以共享下),無論設(shè)置成啥顏色都不起作用。

于是,目光只能投向tickMarkShape,看描述是來繪制tickMark形狀的,其類型為SliderTickMarkShape,默認的實現(xiàn)有RoundSliderTickMarkShape,看其源碼其核心就有一個paint 方法,里面就是用來繪制tickMark的:

@override
  void paint(
    PaintingContext context,
    Offset center, {
    required RenderBox parentBox,
    required SliderThemeData sliderTheme,
    required Animation<double> enableAnimation,
    required TextDirection textDirection,
    required Offset thumbCenter,
    required bool isEnabled,
  }) {
    assert(context != null);
    assert(center != null);
    assert(parentBox != null);
    assert(sliderTheme != null);
    assert(sliderTheme.disabledActiveTickMarkColor != null);
    assert(sliderTheme.disabledInactiveTickMarkColor != null);
    assert(sliderTheme.activeTickMarkColor != null);
    assert(sliderTheme.inactiveTickMarkColor != null);
    assert(enableAnimation != null);
    assert(textDirection != null);
    assert(thumbCenter != null);
    assert(isEnabled != null);
    // The paint color of the tick mark depends on its position relative
    // to the thumb and the text direction.
    Color? begin;
    Color? end;
    switch (textDirection) {
      case TextDirection.ltr:
        final bool isTickMarkRightOfThumb = center.dx > thumbCenter.dx;
        begin = isTickMarkRightOfThumb ? sliderTheme.disabledInactiveTickMarkColor : sliderTheme.disabledActiveTickMarkColor;
        end = isTickMarkRightOfThumb ? sliderTheme.inactiveTickMarkColor : sliderTheme.activeTickMarkColor;
        break;
      case TextDirection.rtl:
        final bool isTickMarkLeftOfThumb = center.dx < thumbCenter.dx;
        begin = isTickMarkLeftOfThumb ? sliderTheme.disabledInactiveTickMarkColor : sliderTheme.disabledActiveTickMarkColor;
        end = isTickMarkLeftOfThumb ? sliderTheme.inactiveTickMarkColor : sliderTheme.activeTickMarkColor;
        break;
    }
    final Paint paint = Paint()..color = ColorTween(begin: begin, end: end).evaluate(enableAnimation)!;

    // The tick marks are tiny circles that are the same height as the track.
    final double tickMarkRadius = getPreferredSize(
       isEnabled: isEnabled,
       sliderTheme: sliderTheme,
     ).width / 2;
    if (tickMarkRadius > 0) {
      context.canvas.drawCircle(center, tickMarkRadius, paint);
    }
  }

上面可以看到只有當 tickMarkRadius > 0 時,才會繪制一個圓圈,為了不讓顯示tickMark我們只需將tickMarkRadius設(shè)置成 <=0 就可以了,最終設(shè)置如下:

SliderTheme(
    data: SliderTheme.of(context).copyWith(
        //這里 tickMarkRadius 設(shè)置成 0 即可
        tickMarkShape: const RoundSliderTickMarkShape(tickMarkRadius: 0)
      ),
    child: Slider(
        min: 1, max: 100, value: _value, divisions: 10, 
        activeColor: Colors.red,
        inactiveColor: Colors.grey,
        onChanged: (value) {
          setState(() {
            _value = value;
          });
        }));

最終效果如下:


tick2.png

除此外,我們還可以自定義一個類來繼承SliderTickMarkShape,在paint方法里什么都不做,同樣可以達到一樣的效果,代碼如下:

class TransparentSliderTickMarkShape extends SliderTickMarkShape {
  @override
  Size getPreferredSize({required SliderThemeData sliderTheme, required bool isEnabled}) {
    return const Size(0, 0);
  }

  @override
  void paint(PaintingContext context, Offset center, {required RenderBox parentBox, required SliderThemeData sliderTheme, required Animation<double> enableAnimation, required Offset thumbCenter, required bool isEnabled, required TextDirection textDirection}) {
    
  }

}

SliderTheme(
      data: SliderTheme.of(context).copyWith(
          activeTickMarkColor: Colors.transparent,
          inactiveTickMarkColor: Colors.transparent,
          tickMarkShape: TransparentSliderTickMarkShape()
        ),
      child: Slider(
          min: 1, max: 100, value: _value, divisions: 10, 
          activeColor: Colors.red,
          inactiveColor: Colors.grey,
          onChanged: (value) {
            setState(() {
              _value = value;
            });
          }))
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容