在我的自定义滑块拇指和轨道中,可以选择不正确的滑块拇指区域进行拖动。代码如下:
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);
}
}
这将呈现以下内容。黑色方块的上半部分不可拖动,而滑块的整个下半部分是可选择的。滑块的上半部分或滑块拇指应该是可选的。
如果我注释掉 trackShape
参数,则可以选择拇指的正确区域。
答案 0 :(得分:0)
可用于调整滑块值的滑块区域由轨道尺寸和拇指尺寸共同配置。如果将拇指配置为 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);
}
}