Slider 滑块控件自定义Thumb

Slider 是 Flutter 中用于选择一个范围内值的控件,通常用于调节音量、亮度等场景。它允许用户通过拖动滑块来选择数值。

一、Slider的基本属性

主要属性

  • value:当前滑块的值。

  • onChanged:当滑块的值发生变化时调用的回调函数。

  • min:滑块的最小值,默认为 0.0。

  • max:滑块的最大值,默认为 1.0。

  • divisions:将滑块分成若干等份,设置后滑块会吸附到这些点上。

  • label:滑块上显示的标签,通常与 divisions 一起使用。

  • activeColor:滑块活动部分的颜色。

  • inactiveColor:滑块非活动部分的颜色。

Slider的其他属性也可以在Flutter文档中查看。

二、自定义Slider滑块样式

通过 SliderTheme 来自定义 Slider 的外观。示例如下:

SliderTheme(
  data: SliderTheme.of(context).copyWith(
    activeTrackColor: Colors.red,
    inactiveTrackColor: Colors.grey,
    thumbColor: Colors.blue,
    overlayColor: Colors.blue.withOpacity(0.2),
    thumbShape: RoundSliderThumbShape(enabledThumbRadius: 12.0),
    overlayShape: RoundSliderOverlayShape(overlayRadius: 20.0),
  ),
  child: Slider(
    value: _currentValue,
    min: 0.0,
    max: 100.0,
    onChanged: (double value) {
      setState(() {
        _currentValue = value;
      });
    },
  ),
);

三、使用Image自定义ThumeShape

如果想要根复杂的滑块样式,可以自定义thumbShape属性,使用Image达到效果。

自定义ImageSliderThumb 继承SliderComponentShape,重写paint函数,绘制自定义滑块样式。

import 'package:flutter/material.dart';
import 'dart:ui' as ui;

class ImageSliderThumb extends SliderComponentShape {
  final Size size;
  final ui.Image? image;

  const ImageSliderThumb({required this.image, Size? size})
      : size = size ?? const Size(20, 20);

  @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}) {
    //图片中心点
    double dx = size.width / 2;
    double dy = size.height / 2;

    if (image != null) {
      final Rect sourceRect =
          Rect.fromLTWH(0, 0, image!.width.toDouble(), image!.width.toDouble());
      //center会随着滑块的移动而改变,所以这里需要根据center计算图片绘制的位置
      double left = center.dx - dx;
      double top = center.dy - dy;
      double right = center.dx + dx;
      double bottom = center.dy + dy;
      Rect destinationRect = Rect.fromLTRB(left, top, right, bottom);

      final Canvas canvas = context.canvas;
      final Paint paint = Paint();
      paint.isAntiAlias = true;
      //绘制滑块
      canvas.drawImageRect(image!, sourceRect, destinationRect, paint);
    }
  }
}

传入的image参数是ui.Image,不能直接使用Image(),方法如下:

  ui.Image? imageInfo;
  Future<void> loadImage() async {
    final ByteData data =
        await rootBundle.load('assets/images.png');//图片路径
    final Codec codec =
        await ui.instantiateImageCodec(data.buffer.asUint8List());
    final FrameInfo frameInfo = await codec.getNextFrame();
    setState(() {
      imageInfo = frameInfo.image;
    });
  }

 调用代码参考:


SliderTheme(
  data: SliderTheme.of(context).copyWith(
     trackHeight: 9, // 设置轨道高度
     inactiveTrackColor: Colors.black.withOpacity(0.1),
     activeTrackColor: Colors.white,
     // 方法调用
     thumbShape: ImageSliderThumb(
         image: imageInfo, size: const Size(22, 22))
     ),
  child: Slider(
           value: 60.0,
           onChanged: (double value) {},
           onChangeEnd: (double value) {},
           min: 0.0,
           max: 100,
         ),
),

四、效果图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HQL_seven

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值