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

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/179705.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Nacos2.x配置中心源码分析

概述 源码注释参考 git 仓库&#xff0c;对应流程图后续补充&#xff1b; 启动 nacos nacos 启动类&#xff1a; // com.alibaba.nacos.NacosSpringBootApplication(scanBasePackages "com.alibaba.nacos") ServletComponentScan EnableScheduling public class…

MySQL事务(简单明了)

目录 1. 事务的特性&#xff08;ACID&#xff09;&#xff1a; 2. 事务的语法&#xff1a; 3. 隔离级别&#xff1a; 4. 保存点&#xff08;Savepoints&#xff09;&#xff1a; 5. 示例&#xff1a; 1. 事务的特性&#xff08;ACID&#xff09;&#xff1a; 原子性&#…

WebUI自动化学习(Selenium+Python+Pytest框架)003

1.元素操作 在成功定位到元素之后&#xff0c;我们需要对元素进行一些操作动作。常用的元素操作动作有&#xff1a; &#xff08;1&#xff09;send_keys() 键盘动作&#xff1a;向浏览器发送一个内容&#xff0c;通常用于输入框输入内容或向浏览器发送快捷键 &#xff08;2…

【数据结构】排序效率最优解之一:二叉树-堆

Hello everybody!今天打算给大家介绍一个功能比较强大的数据结构的基础&#xff0c;它不仅具有很高的应用价值而且排序效率很高。冒泡排序都知道叭&#xff0c;它的时间复杂度为O(n^2)&#xff0c;而堆排序的时间复杂度为O(n*logn)。堆排序直接碾压冒泡排序。在c语言阶段&#…

ELK高级搜索,深度详解ElasticStack技术栈-上篇

前言 1、黑马视频地址&#xff1a;java中级教程-ELK高级搜索&#xff0c;深度详解ElasticStack技术栈 2、本内容仅用于个人学习笔记&#xff0c;如有侵扰&#xff0c;联系删除 1. 课程简介 1.1 课程内容 ELK是包含但不限于Elasticsearch&#xff08;简称es&#xff09;、Lo…

小狐狸ChatGPT付费创作系统V2.3.4独立版 +WEB端+ H5端最新去弹窗授权

ChatGPT付费创作系统V2.3.4版本优化了很多细节&#xff0c;如果使用着2.2.9版本建议没升级的必要。该版本为编译版无开源&#xff0c;2.3.X版本开始官方植入了更多的后门和更隐性的弹窗代码&#xff0c;后门及弹窗处理起来更麻烦。特别针对后台弹窗网址、暗链后门网址全部进行了…

git rebase冲突说明(base\remote\local概念说明)

主线日志及修改 $ git log master -p commit 31213fad6150b9899c7e6b27b245aaa69d2fdcff (master) Author: Date: Tue Nov 28 10:19:53 2023 08004diff --git a/123.txt b/123.txt index 294d779..a712711 100644 --- a/123.txtb/123.txt-1,3 1,4 123 4^Mcommit a77b518156…

网络和Linux网络_6(应用层)HTTPS协议(加密解密+中间人攻击+证书)

目录 1. HTTPS协议介绍 1.1 加密解密和秘钥的概念 1. 2 为什么要加密 2. 对称加密和非对称加密 2.1 只使用对称加密 2.2 只使用非对称加密 2.3 双方都使用非对称加密 2.4 使用非对称加密对称加密 2.5 中间人攻击MITM 3. 证书的概念和HTTPS的通信方式 3.1 CA认证机构…

Redis 事件轮询

1 Redis 为什么快 数据存在内存中, 直接操作内存中的数据单线程处理业务请求避免了多线的上下文切换, 锁竞争等弊端使用 IO 多路复用支撑更高的网络请求使用事件驱动模型, 通过事件通知模式, 减少不必要的等待… 这些都是 Redis 快的原因。 但是这些到了代码层面是如何实现的呢…

基于SSM的论文管理系统的设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

集合框架(二)LinkedList的常见使用

Hi i,m JinXiang ⭐ 前言 ⭐ 本篇文章主要介绍LinkedList的常见使用以及部分理论知识 &#x1f349;欢迎点赞 &#x1f44d; 收藏 ⭐留言评论 &#x1f4dd;私信必回哟&#x1f601; &#x1f349;博主收将持续更新学习记录获&#xff0c;友友们有任何问题可以在评论区留言 目…

Vue2问题:如何全局使用less和sass变量?

前端功能问题系列文章&#xff0c;点击上方合集↑ 序言 大家好&#xff0c;我是大澈&#xff01; 本文约2400字&#xff0c;整篇阅读大约需要4分钟。 本文主要内容分三部分&#xff0c;如果您只需要解决问题&#xff0c;请阅读第一、二部分即可。如果您有更多时间&#xff…

大一学编程怎么学?刚接触编程怎么学习,有没有中文编程开发语言工具?

大一学编程怎么学&#xff1f;刚接触编程怎么学习&#xff0c;有没有中文编程开发语言工具&#xff1f; 1、大一刚开始学编程&#xff0c;面对复杂的代码学习非常吃力&#xff0c;很难入门。建议刚接触编程可以先学习中文编程&#xff0c;了解其中的编程逻辑&#xff0c;学编程…

LeetCode [中等]3. 无重复字符的最长子串

3. 无重复字符的最长子串 - 力扣&#xff08;LeetCode&#xff09; 给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的 最长子串 的长度。 1. 滑动窗口&#xff08;Sliding Window&#xff09;&#xff1a; 滑动窗口是一种用于处理数组或列表的子数组或子序列的问题…

Vue基础入门(四):Vue3快速开发模板

快速开发Vue的解决方案 ​ Vue 的开发需要的 node 环境&#xff0c;其实上在开发的过程中会遇到一些你想不到的问题&#xff0c;比如 npm工具的版本和 node 环境不匹配&#xff08;你把其他项目导入到自己的环境&#xff09; ​ vue-element-admin&#xff08;是一个官方提供…

leetCode 216.组合总和 III + 回溯算法 + 剪枝 + 图解 + 笔记

找出所有相加之和为 n 的 k 个数的组合&#xff0c;且满足下列条件&#xff1a; 只使用数字1到9每个数字 最多使用一次 返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次&#xff0c;组合可以以任何顺序返回 示例 1: 输入: k 3, n 7 输出: [[1,2,4]] 解释…

pinia从入门到使用

pinia: 比vuex更适合vue3的状态管理工具&#xff0c;只保留了vuex 原有的 state, getters&#xff0c;actions 作用等同于 data computed methods&#xff0c;可以有多个 state 1.安装创建导入 安装&#xff1a;npm install pinia 或 yarn add pinia 创建stores/index.js inde…

Jmeter接口测试和性能测试

目前最新版本发展到5.0版本&#xff0c;需要Java7以上版本环境&#xff0c;下载解压目录后&#xff0c;进入\apache-jmeter-5.0\bin\&#xff0c;双击ApacheJMeter.jar文件启动JMemter。 1、创建测试任务 添加线程组&#xff0c;右击测试计划&#xff0c;在快捷菜单单击添加-…

VSCode Vue 开发环境配置

Vue是前端开发中的重要工具与框架&#xff0c;可以保住开发者高效构建用户界面。 Vue2官方文档&#xff1a;https://v2.cn.vuejs.org/ Vue3官方文档&#xff1a;https://cn.vuejs.org/ Vue的安装和引用 Vue2的官方安装指南&#xff1a;https://v2.cn.vuejs.org/v2/guide/ins…

ESP32-Web-Server 实战编程-通过网页控制设备多个 GPIO

ESP32-Web-Server 实战编程-通过网页控制设备多个 GPIO 概述 上节 ESP32-Web-Server 实战编程-通过网页控制设备的 GPIO 讲述了如何通过网页控制一个 GPIO。本节实现在网页上控制多个 GPIO。 示例解析 前端设计 前端代码建立了四个 GPIO&#xff0c;如下死 GPIO 2 在前端的…