Flutter Slider自定义滑块样式 Slider的label标签框常显示

1、自定义Slider滑块样式

Flutter Slider控件的滑块系统样式是一个圆点,thumbShape默认样式是RoundSliderThumbShape,如果想要使用其它的样式就需要自定义一下thumbShape;

例如需要一个上图样式的(圆点+半透明圆形边框)的滑块:


class CustomSliderThumbShape extends SliderComponentShape {

  final Size size = const Size(40, 40);

  @override
  Size getPreferredSize(bool isEnabled, bool isDiscrete) {
    return size;
  }

  @override
  void paint(PaintingContext context, Offset center, {required Animation<double> activationAnimation, required Animation<double> enableAnimation, required bool isDiscrete, required TextPainter labelPainter, required RenderBox parentBox, required SliderThemeData sliderTheme, required TextDirection textDirection, required double value, required double textScaleFactor, required Size sizeWithOverflow}) {

    final Canvas canvas = context.canvas;
    final Paint paint =  Paint();
    paint.color = const Color(0XFFEF5133);
    paint.isAntiAlias = true;

    final Paint paint2 =  Paint();
    paint2.color = const Color(0x30EF5133);
    paint2.isAntiAlias = true;
    //绘制滑块
    canvas.drawCircle(center, 5, paint);
    canvas.drawCircle(center, 14, paint2);
  }
}

然后再使用 SliderThemeData控件的 thumbShape属性设置一下就行了;

          SliderTheme(
            data: SliderThemeData(
              thumbShape: CustomSliderThumbShape(),
            ),
            child: Slider(
            ),
          ),

2、Slider的label标签框常显示

上图,Slider的label标签只有按住滑动块时才会显示,松开手指后label标签就会消失,设置 showValueIndicator: ShowValueIndicator.always,也不能一直显示;

若要Slider的label标签框常显示,可以把label标签框和滑块写在一起,使用SliderComponentShape自定义一下布局;

class IndicatorSliderThumbShape extends SliderComponentShape {

  IndicatorSliderThumbShape(this.msg);

  String msg;

  @override
  Size getPreferredSize(bool isEnabled, bool isDiscrete) {
    return const Size(15, 40);
  }

  TextPainter labelTextPainter = TextPainter()
    ..textDirection = TextDirection.ltr;

  @override
  void paint(PaintingContext context, Offset center, {required Animation<double> activationAnimation, required Animation<double> enableAnimation, required bool isDiscrete, required TextPainter labelPainter, required RenderBox parentBox, required SliderThemeData sliderTheme, required TextDirection textDirection, required double value, required double textScaleFactor, required Size sizeWithOverflow}) {

    final Canvas canvas = context.canvas;
    final Paint paint =  Paint();
    paint.color = const Color(0XFFEF5133);
    paint.isAntiAlias = true;
    //绘制圆点滑块
    canvas.drawCircle(center, 4, paint);

    final Paint paint2 =  Paint();
    paint2.color = const Color(0X30EF5133);
    paint2.isAntiAlias = true;
    //绘制半透明滑块
    canvas.drawCircle(center, 12, paint2);

    //在thumb上面添加一个自定义labels



    //绘制labels的圆角矩形
    final Paint paint3 =  Paint();
    paint3.color = const Color(0xFF2C28E8);
    paint3.isAntiAlias = true;
    var rr =  RRect.fromLTRBXY(center.dx+30, center.dy-20, center.dx-30, center.dy-50 , 8,8);
    canvas.drawRRect(rr, paint3);

    //绘制labels的三角形指示块
    final Paint paint4 =  Paint();
    paint4.color = const Color(0xFF28CD41);
    paint4.isAntiAlias = true;
    final path = Path();
    path.moveTo(center.dx, center.dy-10,);
    path.lineTo(center.dx-10, center.dy-20);
    path.lineTo(center.dx+10, center.dy-20,);
    path.close();

    canvas.drawPath(path, paint4);

    //绘制labels的文字内容
    labelTextPainter.text = TextSpan(
        text: msg,
        style: const TextStyle(fontSize: 14, color: Colors.white));
    labelTextPainter.layout();
    labelTextPainter.paint(
        canvas,
        center.translate(-labelTextPainter.width / 2, -43));

  }
}

label框的文字、指示器箭头、圆角背景框都可以自定义;

同样shape设置一下就可以了:

      SliderTheme(
            data: SliderThemeData(
              thumbShape: IndicatorSliderThumbShape('xx-km'),
            ),
            child: Slider(
            ),
          ),

下面是Slider的全部代码:

class TestSliderPage extends StatefulWidget {
  const TestSliderPage({Key? key}) : super(key: key);

  @override
  State<TestSliderPage> createState() => _TestSliderPageState();
}

class _TestSliderPageState extends State<TestSliderPage> {
  double _sliderValue = 0;
  final List<int> _slideValues = [1,3,5,10,20,30,40,50,60,70,80,90,100];
  @override
  Widget build(BuildContext context) {
    return BaseTopView(title: "Slider",
      body:
        Container(
          color: color_fff,
          child: SliderTheme(
            data: SliderThemeData(
              thumbShape: IndicatorSliderThumbShape('${_slideValues[_sliderValue.toInt()]}km'),
              trackHeight: ScreenUtils.getDip(1.5),
              thumbColor: color_EF5133,
              //滑块颜色
              activeTrackColor: color_EF5133,
              //已选中颜色
              inactiveTrackColor: color_EF5133.withAlpha(15),
              //未选中颜色
              activeTickMarkColor: Colors.transparent,
              //指示器点颜色
              inactiveTickMarkColor: Colors.transparent,
              //指示器点颜色
              valueIndicatorColor: color_EF5133,
              //气泡颜色
              overlayColor: color_EF5133.withAlpha(15),
              showValueIndicator: ShowValueIndicator.never,
              valueIndicatorTextStyle: TextStyle(fontSize: 11),
            ),
            child: Slider(
              value: _sliderValue,
              min: 0,
              max: 12,
              onChanged: (newValue) {
                setState(() {
                  _sliderValue = newValue;
                });
              },
              label: '${_slideValues[_sliderValue.toInt()]}km',
              divisions: _slideValues.length - 1,
            ),
          ),
      ),);
  }
}

随手记录、、、

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值