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…...
ES6从入门到精通:前言
ES6简介 ES6(ECMAScript 2015)是JavaScript语言的重大更新,引入了许多新特性,包括语法糖、新数据类型、模块化支持等,显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var…...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)
引言 在人工智能飞速发展的今天,大语言模型(Large Language Models, LLMs)已成为技术领域的焦点。从智能写作到代码生成,LLM 的应用场景不断扩展,深刻改变了我们的工作和生活方式。然而,理解这些模型的内部…...
NPOI操作EXCEL文件 ——CAD C# 二次开发
缺点:dll.版本容易加载错误。CAD加载插件时,没有加载所有类库。插件运行过程中用到某个类库,会从CAD的安装目录找,找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库,就用插件程序加载进…...

pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)
目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 (1)输入单引号 (2)万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...
Qt 事件处理中 return 的深入解析
Qt 事件处理中 return 的深入解析 在 Qt 事件处理中,return 语句的使用是另一个关键概念,它与 event->accept()/event->ignore() 密切相关但作用不同。让我们详细分析一下它们之间的关系和工作原理。 核心区别:不同层级的事件处理 方…...
Python 高效图像帧提取与视频编码:实战指南
Python 高效图像帧提取与视频编码:实战指南 在音视频处理领域,图像帧提取与视频编码是基础但极具挑战性的任务。Python 结合强大的第三方库(如 OpenCV、FFmpeg、PyAV),可以高效处理视频流,实现快速帧提取、压缩编码等关键功能。本文将深入介绍如何优化这些流程,提高处理…...

Appium下载安装配置保姆教程(图文详解)
目录 一、Appium软件介绍 1.特点 2.工作原理 3.应用场景 二、环境准备 安装 Node.js 安装 Appium 安装 JDK 安装 Android SDK 安装Python及依赖包 三、安装教程 1.Node.js安装 1.1.下载Node 1.2.安装程序 1.3.配置npm仓储和缓存 1.4. 配置环境 1.5.测试Node.j…...

ABAP设计模式之---“Tell, Don’t Ask原则”
“Tell, Don’t Ask”是一种重要的面向对象编程设计原则,它强调的是对象之间如何有效地交流和协作。 1. 什么是 Tell, Don’t Ask 原则? 这个原则的核心思想是: “告诉一个对象该做什么,而不是询问一个对象的状态再对它作出决策。…...

持续交付的进化:从DevOps到AI驱动的IT新动能
文章目录 一、持续交付的本质:从手动到自动的交付飞跃关键特性案例:电商平台的高效部署 二、持续交付的演进:从CI到AI驱动的未来发展历程 中国…...