04_Flutter自定义Slider滑块

这篇具有很好参考价值的文章主要介绍了04_Flutter自定义Slider滑块。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

04_Flutter自定义Slider滑块

一.Slider控件基本用法
Column(
  mainAxisAlignment: MainAxisAlignment.start,
  children: <Widget>[
    Text(
      "sliderValue: ${_sliderValue.toInt()}"
    ),
    Slider(
      value: _sliderValue,
      min: 0,
      max: 100,
      divisions: 10,
      thumbColor: Colors.red,
      activeColor: Colors.red,
      onChanged: (value) {
        setState(() {
          _sliderValue = value;
        });
      }
    )
  ],
)

flutter slider自定义thumb,重学Flutter,flutter,android,ios,移动开发

const Slider({
    super.key,
    required this.value,
    this.secondaryTrackValue,
    required this.onChanged,
    this.onChangeStart,
    this.onChangeEnd,
    this.min = 0.0,
    this.max = 1.0,
    this.divisions,
    this.label,
    this.activeColor,
    this.inactiveColor,
    this.secondaryActiveColor,
    this.thumbColor,
    this.overlayColor,
    this.mouseCursor,
    this.semanticFormatterCallback,
    this.focusNode,
    this.autofocus = false,
  })

几个比较重要的属性:

  • value:slider控件显示的值
  • min:slider控件滑动到最左边对应的值,即最小值
  • max: slider控件滑动到最右边对应的值,即最大值
  • divisions: 最小值到最大值之间被几等分
  • activeColor: 滑块划过部分的颜色值,即选中的颜色值
  • inactiveColor:滑块未划过部分的颜色值,即为选中的颜色值
  • thumbColor:滑块的颜色值
二.如何修改滑块的大小以及滑块轨迹的高度

从上面的示例可以看到,通过Slider控件为我们提供的属性,只支持改变滑块的颜色,以及滑块轨迹的颜色,那么我们想要改变滑块的大小以及滑块轨迹的高度,是不是只能重新自定义呢?

NO! NO! NO!,细心的您在使用Flutter的AppBar时,可能会发现,为AppBar控件指定样式时,除了使用AppBar控件提供的属性外,也可以使用AppBarTheme来为AppBar设置某些特定的样式,既然如此,不妨查看下Flutter sdk的源码与Slider对应的是否有一个叫SliderTheme的控件呢? 嘿嘿,还真有。

final SliderThemeData data;
const SliderTheme({
  super.key,
  required this.data,
  required super.child,
});

const SliderThemeData({
  this.trackHeight,
  this.thumbShape,
  ...
});

仔细找SliderThemeData的trackHeight以及thumbShape的属性注释:

/// The height of the [Slider] track.
final double? trackHeight;

/// The shape that will be used to draw the [Slider]'s thumb.
/// The default value is [RoundSliderThumbShape].
final SliderComponentShape? thumbShape;

此处省略…翻译软件的时间:

  • trackHeight:[滑块]轨迹的高度
  • thumbShape:默认值是一个RoundSliderThumbShape对象

看下RoundSliderThumbShape的源码怎么写的:

const RoundSliderThumbShape({
  this.enabledThumbRadius = 10.0,
  this.disabledThumbRadius,
  this.elevation = 1.0,
  this.pressedElevation = 6.0,
});

看到这里就不用做过多的解释了吧😂,因此要修改滑块的大小,可以重新指定thumbShape为RoundSliderThumbShape对象,并设置enabledThumbRadius的值。

flutter slider自定义thumb,重学Flutter,flutter,android,ios,移动开发

Column(
  mainAxisAlignment: MainAxisAlignment.start,
  children: <Widget>[
    Text(
      "sliderValue: ${_sliderValue.toInt()}"
    ),
    SliderTheme(
      data: const SliderThemeData(
        trackHeight: 20,
        thumbShape: RoundSliderThumbShape(
          enabledThumbRadius: 20
        )
      ),
      child: Slider(
        value: _sliderValue,
        min: 0,
        max: 100,
        divisions: 10,
        thumbColor: Colors.red,
        activeColor: Colors.red,
        onChanged: (value) {
          setState(() {
            _sliderValue = value;
          });
        }
      )
    )
  ],
)
三.使用本地资源图片作为自定义滑块

既然要自定义滑块,毫无疑问需要从SliderThemeData的thumbShape入手。

final SliderComponentShape? thumbShape;

thumbShape的类型为SliderComponentShape,继续查看SliderComponentShape源码:

abstract class SliderComponentShape {

  const SliderComponentShape();

  Size getPreferredSize(bool isEnabled, bool isDiscrete);

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

因此我们可以定义一个类继承SliderComponentShape,并实现getPreferredSize和paint方法,getPreferredSize控制滑块大小,paint负责把滑块绘制到屏幕上。

  • 首先第一步我们需要将本地图片为一个ImageInfo,例如传入一个"lib/assets/images/ic_slider_thumb.png",最后得到一个ImageInfo,这里就直接奉上源码了,其实现也是参考了Image.asset的源码:
typedef AssertsWidgetBuilder = Widget Function(BuildContext context, ImageInfo? imageInfo);

class AssertsImageBuilder extends StatefulWidget {

  final String assertsName;
  final AssertsWidgetBuilder builder;

  const AssertsImageBuilder(
    this.assertsName,
    {
      super.key,
      required this.builder,
    }
  );

  
  State<StatefulWidget> createState() => _AssertsImageBuilderState();

}

class _AssertsImageBuilderState extends State<AssertsImageBuilder> {

  ImageInfo? _imageInfo;

  
  void initState() {
    super.initState();
    _loadAssertsImage().then((value) {
      setState(() {
        _imageInfo = value;
      });
    });

  }

  
  void didUpdateWidget(covariant AssertsImageBuilder oldWidget) {
    super.didUpdateWidget(oldWidget);
    if(oldWidget.assertsName != widget.assertsName) {
      _loadAssertsImage().then((value) {
        setState(() {
          _imageInfo = value;
        });
      });
    }
  }

  
  Widget build(BuildContext context) {
    return widget.builder!.call(context, _imageInfo);
  }

  Future<ImageInfo?> _loadAssertsImage() {
    final Completer<ImageInfo?> completer = Completer<ImageInfo?>();
    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
      final ImageProvider imageProvider = AssetImage(widget.assertsName);
      final ImageConfiguration config = createLocalImageConfiguration(context);
      final ImageStream stream = imageProvider.resolve(config);
      ImageStreamListener? listener;
      listener = ImageStreamListener(
            (ImageInfo? image, bool sync) {
          if (!completer.isCompleted) {
            completer.complete(image);
          }

          SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) {
            stream.removeListener(listener!);
          });
        },
        onError: (Object exception, StackTrace? stackTrace) {
          stream.removeListener(listener!);
          completer.completeError(exception, stackTrace);
        },
      );
      stream.addListener(listener);
    });

    return completer.future;
  }

}
  • 自定义SliderComponentShape
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);

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

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

}
  • 绘制图片滑块

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 = new Paint();
    paint.isAntiAlias = true;
    //绘制滑块
    canvas.drawImageRect(image!, sourceRect, destinationRect, paint);
  }
}
四.怎么使用?
Column(
  mainAxisAlignment: MainAxisAlignment.start,
  children: <Widget>[
    Text(
      "sliderValue: ${_sliderValue.toInt()}"
    ),
    AssertsImageBuilder(
      "lib/assets/images/ic_slider_thumb.png",
      builder: (context, imageInfo) {
        return SliderTheme(
          data: SliderThemeData(
            trackHeight: 10,
            thumbShape: ImageSliderThumb(
              image: imageInfo?.image,
              size: const Size(30, 30)
            )
          ),
          child: Slider(
            value: _sliderValue,
            min: 0,
            max: 100,
            divisions: 10,
            thumbColor: Colors.red,
            activeColor: Colors.red,
            onChanged: (value) {
              setState(() {
                _sliderValue = value;
              });
            }
          )
        );
      }
    ),
  ],
)

flutter slider自定义thumb,重学Flutter,flutter,android,ios,移动开发文章来源地址https://www.toymoban.com/news/detail-827832.html

到了这里,关于04_Flutter自定义Slider滑块的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 16.鸿蒙HarmonyOS App(JAVA)滑块组件Slider与评级组件Rating

      16.鸿蒙HarmonyOS App(JAVA)滑块组件Slider与评级组件Rating  ability_main.xml     MainAbilitySlice.java  

    2024年01月19日
    浏览(38)
  • uniapp-vue2-微信小程序-滑块验证组件wo-slider

    wo-slider是一款支持高度自定义的滑块验证组件,采用uniapp-vue2编写 采用touchstart、touchmove、touchend事件实现的滑块组件,支持H5、微信小程序(其他小程序未试过,可自行尝试) 可到插件市场下载尝试: https://ext.dcloud.net.cn/search?q=wo-slider 使用示例

    2024年02月07日
    浏览(38)
  • Android 滑动条、Slider、Seekbar深度自定义

    为了更好的满足日常开发中对Slider控件的各种需要,以下我们来看下基于nifty-slider来定制我们所需的各种功能及交互效果 支持滑动条起始值结束值的自定义 支持滑动条指定步长以实现类似刻度的功能 支持对滑块的自定义以添加光环效果、滑块形状,滑块投影、滑块边框、滑

    2024年02月12日
    浏览(41)
  • 038-第三代软件开发-简易视频播放器-自定义Slider (二)

    : Qt 、 Qml 、 3 、 4 、 5 欢迎来到我们的 QML C++ 项目!这个项目结合了 QML(Qt Meta-Object Language)和 C++ 的强大功能,旨在开发出色的用户界面和高性能的后端逻辑。 在项目中,我们利用 QML 的声明式语法和可视化设计能力创建出现代化的用户界面。

    2024年02月07日
    浏览(33)
  • Flutter笔记:滑块及其实现分析1

    Flutter笔记 滑块分析1 作者 : 李俊才 (jcLee95):https://blog.csdn.net/qq_28550263 邮箱 : 291148484@163.com 本文地址 :https://blog.csdn.net/qq_28550263/article/details/134900784 本文从设计角度,考虑滑块组件的使用场景,实现一个滑块组件应该包含的功能,介绍 Flutter 中滑块组件的用法,并分析

    2024年02月05日
    浏览(40)
  • WPF的范围控件Slider

    名称 说明 Orientation 在竖直滑动条和水平滑动条之间切换 TickPlacement 决定刻度显示的位置,默认情况下,TickPlacement被设置为None,并且不显示刻度标记,如果是水平滑动条,可在上面放置刻度标记(TopLeft)或在下面放置刻度标记(BottomRight)。对于竖直滑动条,可在左边(To

    2024年02月12日
    浏览(40)
  • 第五十九回: Slider Widget

    我们在上一章回中介绍了Form Widget相关的内容,本章回中将介绍 Slider Widget.闲话休提,让我们一起Talk Flutter吧。 我们在这里说的 Slider Widget是一种滑动条组件,通过滑动来控制不同的进度,它类似进度条,不过需要我们让去去滑动它的是进度,在实际项目中经常用它来调节音

    2024年02月09日
    浏览(42)
  • Unity-Slider调节音量大小功能

    Slider在Unity中的用法有许多,我们可以用它来调节音量大小、视频进度条及角色的血量条等,本文章我们来学习一下第一个功能吧~ 1.新建一个空物体,按F2快捷键修改名称为“Background music”; 2.在“Background music”空物体中添加“Audio Source”组件→在AudioClip添加背景音乐→勾选

    2024年02月13日
    浏览(43)
  • Android Jetpack Compose — Slider滑动条

            在Android Jetpack Compose中,Slider(滑动条)是一个常用的用户界面控件,它允许通过滑动条来选择一个范围或数值。Slider控件非常适用于调整音量、亮度、进度等需要连续调整的场景。 一、Slider的属性         Slider是Android Jetpack Compose中的一个控件,用于实现滑动条

    2024年02月11日
    浏览(48)
  • 【Unity入门】UGUI之Slider(滑动条)

    Slider控件允许用户可以通过鼠标来在预先确定的范围调节数值 我们可以在Hierarchy视图右键 - UI -Slider来创建滑动条 通过上图可以发现Unity内置的Slider主要有3部分,一个是最底层的Background,然后是Fill(进度),然后就是Handle(圆点) 注意:Handle可以去除,其并不是必须的。去

    2024年02月22日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包