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

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的值。

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

相关文章:
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.…...
服务器数据恢复—EMC存储raid5故障导致上层应用崩溃的数据恢复案例
服务器存储数据恢复环境: EMC某型号存储,8块组建一组raid5磁盘阵列。上层操作系统采用zfs文件系统。 服务器存储故障&分析: raid5阵列中有2块硬盘未知原因离线,raid5阵列崩溃,上层应用无法正常使用。 服务器数据恢…...
7.1 Windows驱动开发:内核监控进程与线程回调
在前面的文章中LyShark一直在重复的实现对系统底层模块的枚举,今天我们将展开一个新的话题,内核监控,我们以监控进程线程创建为例,在Win10系统中监控进程与线程可以使用微软提供给我们的两个新函数来实现,此类函数的原…...
基于ssm的汽车论坛管理系统设计与实现
基于ssm的汽车论坛管理系统设计与实现 摘要:信息化社会内需要与之针对性的信息获取途径,但是途径的扩展基本上为人们所努力的方向,由于站在的角度存在偏差,人们经常能够获得不同类型信息,这也是技术最为难以攻克的课题…...
实习开发日志经验总结(一)
文章目录 前言实习日志经验总结 前言 自己之前实习过程中遇到的问题以及相应的解决过程,我都有记录形成比较凌乱的实习日志。故想在整个实习日志的基础上,提炼一些技术知识点或者是解决问题的思路。考虑到实习项目的不方便公开性,所以会隐去…...
【Unity基础】8.简单场景的搭建
【Unity基础】8.简单场景的搭建 大家好,我是Lampard~~ 欢迎来到Unity基础系列博客,所学知识来自B站阿发老师~感谢 (一)场景资源 (1)Import资源包 今天我们将手动去搭一个简单的场景,当…...
傅里叶变换及其在机器学习中的应用
一、介绍 傅立叶变换是一种数学技术,在各个科学和工程领域发挥着关键作用,其应用范围从信号处理到量子力学。近年来,它在机器学习领域发现了新的意义。本文探讨了傅里叶变换的基础知识及其在机器学习应用中日益增长的重要性。 …...
xorm源码学习
文章目录 XORM源码浅析及实践ORMORM vs. SQLXORM软件架构 ORM 引擎 Engine——DBM*core.DB Golang:database/sql 源码基本结构连接复用,提高性能。增加数据库连接池数量连接管理 database/sql主要内容:sql.DB创建数据库连接sql.Open()DB.conn…...
Vue3中的<script setup>和<script>的区别
相同点 在一个 Vue3 单文件组件 (SFC)中,<script setup> 和 <script> 它们各自最多只能存在一个。 不同点 <script setup> 这个脚本块将被预处理为组件的 setup() 函数,这意味着它将为每一个(也可以说每一次)组件实例都执行。 <…...
Docker笔记-Docker搭建最新版zabbix服务端(2023-07-31)
前言 一开始问chartgpt上,搭建的思路是对的,但命令和细节有问题,最后还是依靠StackOverflow解决的。一开始在amd的linux上搭建好docker版的zabbix,但放到arm的机器上就报错了,原因是指令集不匹配,最后跑到…...
QT配合CSS隐藏按钮
第一种方法 在Qt的CSS样式表中,使用 visibility 属性来隐藏按钮。设置 visibility 为 hidden 不可见,而设置为 visible 则可见。 隐藏所有 QPushButton QPushButton {visibility: hidden; }隐藏特定的按钮,用按钮的名称或样式类进行定位就…...
2023亚太地区数学建模C题思路分析+模型+代码+论文
目录 1.2023亚太地区各题思路模型:比赛开始后,第一时间更新,获取见文末名片 3 常见数模问题常见模型分类 3.1 分类问题 3.2 优化问题 详细思路见此名片,开赛第一时间更新 1.亚太地区数学建模ABC题思路模型:9比赛开…...
Linguistic Steganalysis in Few-Shot Scenario论文阅读笔记
TIFS期刊 A类期刊 新知识点 Introduction Linguistic Steganalysis in Few-Shot Scenario模型是个预训练方法。 评估了四种文本加密分析方法,TS-CSW、TS-RNN、Zou、SeSy,用于分析和训练的样本都由VAE-Stego生产(编码方式使用AC编码)。 实验是对比在少样…...
详细学习Pyqt5的4种项目部件(Item Widget)
Pyqt5相关文章: 快速掌握Pyqt5的三种主窗口 快速掌握Pyqt5的2种弹簧 快速掌握Pyqt5的5种布局 快速弄懂Pyqt5的5种项目视图(Item View) 快速弄懂Pyqt5的4种项目部件(Item Widget) 快速掌握Pyqt5的6种按钮 快速掌握Pyqt5的10种容器&…...
notepad++ 插件JSONView安装
1,前提 开发过程中经常需要处理json格式语句,需要对json数据格式化处理,因为使用的是虚拟机内开发,所以没法连接外网,只能在本地电脑下载插件后,然后上传到虚拟机中,进行安装使用。 2…...
AKConv:具有任意采样形状和任意数目参数的卷积核
文章目录 摘要1、引言2、相关工作3、方法3.1、定义初始采样位置3.2、可变卷积操作3.3、扩展AKConv3.3、扩展AKConv 4、实验4.1、在COCO2017上的目标检测实验4.2、在VOC 712上的目标检测实验4.3、在VisDrone-DET2021上的目标检测实验4.4、比较实验4.5、探索初始采样形状 5、分析…...
如何使用C++开发集群服务
开发集群服务需要掌握以下技术: 分布式系统原理:了解集群的概念、工作原理、负载均衡、容错等相关概念。 网络编程:掌握Socket编程和HTTP协议等。 C编程:熟练掌握C语言的基础知识和STL等常用库。 多线程编程:了解线…...
docker安装以及idea访问docker
其他目录: docker 安装环境: https://blog.csdn.net/gd898989/article/details/134570167 docker 打包java包,并运行(有空更新) url “” docker 打包vue (有空更新) url “” docker 多服务 (…...
激光切割头组件中喷嘴的作用是什么
喷嘴是一个不可忽视的部件。尽管喷嘴并不起眼,却有着重要的作用;喷嘴一般是与激光切割头同轴的,且形状多样:圆柱形、锥形、缩放型等。 喷嘴的口径尺寸时不相同的,大口径的喷嘴对聚焦来的激光束没有很严苛的要求;而口径…...
腾讯云双11活动最后一天,错过再等一年!
腾讯云双11活动已经进入尾声,距离活动结束仅剩最后一天,记得抓住这次上云好时机,错过这次,就要等到下一年才能享受到这样的优惠力度了! 活动地址: 点此直达腾讯云双11活动主会场 活动详情: 1…...
未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...
在WSL2的Ubuntu镜像中安装Docker
Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包: for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...
JS手写代码篇----使用Promise封装AJAX请求
15、使用Promise封装AJAX请求 promise就有reject和resolve了,就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...
【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看
文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...
解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用
在工业制造领域,无损检测(NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统,以非接触式光学麦克风技术为核心,打破传统检测瓶颈,为半导体、航空航天、汽车制造等行业提供了高灵敏…...
加密通信 + 行为分析:运营商行业安全防御体系重构
在数字经济蓬勃发展的时代,运营商作为信息通信网络的核心枢纽,承载着海量用户数据与关键业务传输,其安全防御体系的可靠性直接关乎国家安全、社会稳定与企业发展。随着网络攻击手段的不断升级,传统安全防护体系逐渐暴露出局限性&a…...
