Flutter 自定义滑块拇指可选区域与自定义滑块轨迹不正确
在我的自定义滑块拇指和轨迹中,可以选择滑块拇指的错误区域进行拖动。代码如下:Flutter 自定义滑块拇指可选区域与自定义滑块轨迹不正确,flutter,dart,Flutter,Dart,在我的自定义滑块拇指和轨迹中,可以选择滑块拇指的错误区域进行拖动。代码如下: import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold(
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Column(
children: [
SizedBox(height: 100),
Row(children: [
SizedBox(width: 100),
CustomSlider()
])
]
)
)
);
}
}
class CustomSlider extends StatefulWidget {
CustomSlider({Key? key}) : super(key: key);
@override
_CustomSliderState createState() => _CustomSliderState();
}
class _CustomSliderState extends State<CustomSlider> {
double _value = .5;
@override
Widget build(BuildContext context) {
return SliderTheme(
data: SliderThemeData(
thumbShape: _SliderThumbImage(),
trackShape: _SliderTrack(), // Commenting results in correct selectable thumb region
),
child: Slider(
min: .1, max: 1, value: _value,
onChanged: (value) => setState(() { _value = value; })
));
}
}
class _SliderThumbImage extends SliderComponentShape {
static const thumbSideLength = 60.0;
@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}) {
final canvas = context.canvas;
Offset thumbDrawOffset = Offset(center.dx - (thumbSideLength / 2), center.dy - (thumbSideLength / 2));
canvas.drawRect(Rect.fromLTWH(thumbDrawOffset.dx, thumbDrawOffset.dy, thumbSideLength, thumbSideLength),
Paint()..color = Colors.black);
}
@override
Size getPreferredSize(bool isEnabled, bool isDiscrete) {
return Size(thumbSideLength, thumbSideLength);
}
}
class _SliderTrack extends SliderTrackShape {
static const width = 184.0;
static const trackHeight = 16.0;
@override
Rect getPreferredRect(
{required RenderBox parentBox, Offset offset = Offset.zero, required SliderThemeData sliderTheme, bool isEnabled = true, bool isDiscrete = true}) {
return Rect.fromLTWH(0, 0, width, trackHeight);
}
@override
void paint(PaintingContext context, Offset offset,
{required RenderBox parentBox, required SliderThemeData sliderTheme, required Animation<double> enableAnimation, required Offset thumbCenter, bool isEnabled = true, bool isDiscrete = true, required TextDirection textDirection}) {
final canvas = context.canvas;
canvas.drawLine(
Offset(offset.dx, offset.dy + trackHeight / 2),
Offset(offset.dx + width, offset.dy + trackHeight / 2),
Paint()
..color = Colors.amber
..strokeCap = StrokeCap.round
..strokeWidth = trackHeight);
}
}
导入“包装:颤振/材料.省道”;
void main(){
runApp(MyApp());
}
类MyApp扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回材料PP(
家:脚手架(
正文:专栏(
儿童:[
尺寸箱(高度:100),
世界其他地区(儿童:[
尺寸箱(宽度:100),
自定义滑块()
])
]
)
)
);
}
}
类CustomSlider扩展StatefulWidget{
CustomSlider({Key?Key}):超级(Key:Key);
@凌驾
_CustomSliderState createState()=>\u CustomSliderState();
}
类_CustomSliderState扩展状态{
双_值=.5;
@凌驾
小部件构建(构建上下文){
返回滑块主题(
数据:SliderThemeData(
拇指形状:_SliderThumbImage(),
trackShape:_SliderTrack(),//注释结果为正确的可选择拇指区域
),
子:滑块(
最小值:1,最大值:1,值:_值,
onChanged:(value)=>setState((){u value=value;})
));
}
}
类_SliderThumbImage扩展了SliderComponentShape{
静态常数thumbSideLength=60.0;
@凌驾
空白绘制(绘制上下文、偏移中心、,
{必需的动画激活动画,必需的动画启用动画,必需的bool isDiscrete,必需的TextPainter labelPainter,必需的RenderBox parentBox,必需的SliderThemeData sliderTheme,必需的TextDirection TextDirection,必需的double value,必需的double textScaleFactor,必需的sizeWithOverflow}){
最终画布=context.canvas;
偏移量thumbDrawOffset=偏移量(center.dx-(thumbSideLength/2),center.dy-(thumbSideLength/2));
canvas.drawRect(Rect.fromLTWH(thumbDrawOffset.dx,thumbDrawOffset.dy,thumbSideLength,thumbSideLength),
油漆()…颜色=颜色。黑色);
}
@凌驾
大小getPreferredSize(布尔值已启用,布尔值已分离){
返回大小(thumbSideLength、thumbSideLength);
}
}
类\u SliderTrack扩展SliderTrackShape{
静态常数宽度=184.0;
静态常数轨道高度=16.0;
@凌驾
Rect getPreferredRect(
{必需的RenderBox parentBox,Offset Offset=Offset.zero,必需的SliderThemeData sliderTheme,bool isEnabled=true,bool isDiscrete=true}){
从LTWH返回矩形(0,0,宽度,轨迹高度);
}
@凌驾
无效绘制(绘制上下文、偏移、,
{必需的RenderBox parentBox、必需的SliderThemeData sliderTheme、必需的动画启用动画、必需的偏移量thumbCenter、bool isEnabled=true、bool isDiscrete=true、必需的TextDirection TextDirection}){
最终画布=context.canvas;
帆布拉丝(
偏移量(Offset.dx,Offset.dy+轨道高度/2),
偏移量(Offset.dx+宽度,Offset.dy+轨高/2),
油漆()
…颜色=颜色。琥珀色
..strokeCap=strokeCap.round
..行程宽度=轨道高度);
}
}
这将呈现以下内容。黑色正方形的上半部分不可用于拖动,而滑块的整个下半部分可用于拖动。滑块的上半部分或滑块拇指应该是可选的
如果注释掉
trackShape
参数,则拇指的正确区域是可选择的。可选择用于调整滑块值的滑块区域由轨迹尺寸和拇指尺寸配置。如果将拇指配置为50x50,轨迹配置为100x10,则可选择的区域是滑块的50x100边界框,而不是50x50拇指区域。例如,下面突出显示的区域是可选区域:
这也是没有主题的默认滑块的行为
考虑到这一点,我在这个边界框中适当地绘制了轨迹和拇指偏移
import 'package:flutter/material.dart';
const thumbSideLength = 60.0;
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Column(
children: [
SizedBox(height: 100),
Row(children: [
SizedBox(width: 100),
CustomSlider()
])
]
)
)
);
}
}
class CustomSlider extends StatefulWidget {
CustomSlider({Key? key}) : super(key: key);
@override
_CustomSliderState createState() => _CustomSliderState();
}
class _CustomSliderState extends State<CustomSlider> {
double _value = .5;
@override
Widget build(BuildContext context) {
return SliderTheme(
data: SliderThemeData(
thumbShape: _SliderThumbImage(),
trackShape: _SliderTrack(), // Commenting results in correct selectable thumb region
),
child: Slider(
min: .1, max: 1, value: _value,
onChanged: (value) => setState(() { _value = value; })
));
}
}
class _SliderThumbImage extends SliderComponentShape {
@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}) {
final canvas = context.canvas;
Offset thumbCenter = Offset(center.dx, thumbSideLength/2);
canvas.drawRect(Rect.fromCenter(center: thumbCenter, width: thumbSideLength, height: thumbSideLength), Paint()..color = Colors.black);
}
@override
Size getPreferredSize(bool isEnabled, bool isDiscrete) {
return Size(thumbSideLength, thumbSideLength);
}
}
class _SliderTrack extends SliderTrackShape {
static const width = 184.0;
static const trackHeight = 16.0;
@override
Rect getPreferredRect(
{required RenderBox parentBox, Offset offset = Offset.zero, required SliderThemeData sliderTheme, bool isEnabled = true, bool isDiscrete = true}) {
return Rect.fromLTWH(0, 0, width, trackHeight);
}
@override
void paint(PaintingContext context, Offset offset,
{required RenderBox parentBox, required SliderThemeData sliderTheme, required Animation<double> enableAnimation, required Offset thumbCenter, bool isEnabled = true, bool isDiscrete = true, required TextDirection textDirection}) {
final canvas = context.canvas;
canvas.drawLine(
Offset(offset.dx, offset.dy + thumbSideLength/2),
Offset(offset.dx + width, offset.dy + thumbSideLength / 2),
Paint()
..color = Colors.amber
..strokeCap = StrokeCap.round
..strokeWidth = trackHeight);
}
}
导入“包装:颤振/材料.省道”;
常数thumbSideLength=60.0;
void main(){
runApp(MyApp());
}
类MyApp扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回材料PP(
家:脚手架(
正文:专栏(
儿童:[
尺寸箱(高度:100),
世界其他地区(儿童:[
尺寸箱(宽度:100),
自定义滑块()
])
]
)
)
);
}
}
类CustomSlider扩展StatefulWidget{
CustomSlider({Key?Key}):超级(Key:Key);
@凌驾
_CustomSliderState createState()=>\u CustomSliderState();
}
类_CustomSliderState扩展状态{
双_值=.5;
@凌驾
小部件构建(构建上下文){
返回滑块主题(
数据:SliderThemeData(
拇指形状:_SliderThumbImage(),
trackShape:_SliderTrack(),//注释结果为正确的可选择拇指区域
),
子:滑块(
最小值:1,最大值:1,值:_值,
onChanged:(value)=>setState((){u value=value;})
));
}
}
类_SliderThumbImage扩展了SliderComponentShape{
@凌驾
空白绘制(绘制上下文、偏移中心、,
{必需的动画激活动画,必需的动画启用动画,必需的bool isDiscrete,必需的TextPainter labelPainter,必需的RenderBox parentBox,必需的SliderThemeData sliderTheme,必需的TextDirection TextDirection,必需的double value,必需的double textScaleFactor,必需的sizeWithOverflow}){
最终画布=context.canvas;
偏置拇指中心=偏置(center.dx,拇指边长/2);
canvas.drawRect(Rect.fromCenter(中心:拇指中心,宽度:拇指边长,高度:拇指边长),Paint()…color=Colors.black);
}
@凌驾
大小getPreferredSize(布尔值已启用,布尔值已分离){
返回大小(拇指)