Skip to content

Commit

Permalink
Add divisions property to ZenitSlider
Browse files Browse the repository at this point in the history
  • Loading branch information
larsb24 committed Jan 30, 2024
1 parent 9dde1c4 commit 5fab511
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 23 deletions.
1 change: 1 addition & 0 deletions example/lib/pages/slider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class _SliderExampleState extends State<SliderExample> {
child: Padding(
padding: const EdgeInsets.all(32.0),
child: ZenitSlider(
divisions: 10,
onChanged: (val) {
setState(() {
value = val;
Expand Down
79 changes: 56 additions & 23 deletions lib/src/components/slider/slider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ class ZenitSlider extends StatefulWidget {
final ValueChanged<double> onChanged;

final Color? activeColor;
// TODO: implement divisions
//final int? divisions;
final int? divisions;
final Color? trackColor;
final MouseCursor? mouseCursor;
final Color? thumbColor;
Expand All @@ -17,22 +16,27 @@ class ZenitSlider extends StatefulWidget {
required this.value,
required this.onChanged,
this.activeColor,
//this.divisions,
this.divisions,
this.trackColor,
this.mouseCursor,
this.thumbColor,
}) : assert(value >= 0.0 && value <= 1.0);
}) : assert(
value >= 0.0 && value <= 1.0 && divisions == null ||
divisions != null && divisions > 0 && divisions <= 100,
);

@override
State<ZenitSlider> createState() => _ZenitSliderState();
}

class _ZenitSliderState extends State<ZenitSlider> {
bool hover = false;

@override
Widget build(BuildContext context) {
final sliderTheme = ZenitTheme.sliderTheme(context);
double newValue = widget.value;
final double divident = 1 / (widget.divisions ?? 1);
return LayoutBuilder(
builder: (context, constraints) {
return MouseRegion(
Expand All @@ -42,18 +46,19 @@ class _ZenitSliderState extends State<ZenitSlider> {
child: Listener(
onPointerPanZoomStart: (details) {
newValue = details.localPosition.dx / (constraints.maxWidth);
widget.onChanged(newValue);
if (widget.divisions != null) newValue = (newValue / divident).round() * divident;
if (newValue >= 0.0 && newValue <= 1.0) widget.onChanged(newValue);
},
child: GestureDetector(
onTapDown: (details) {
newValue = details.localPosition.dx / (constraints.maxWidth);
widget.onChanged(newValue);
if (widget.divisions != null) newValue = (newValue / divident).round() * divident;
if (newValue >= 0.0 && newValue <= 1.0) widget.onChanged(newValue);
},
onHorizontalDragUpdate: (details) {
newValue += details.delta.dx / constraints.maxWidth;
if (newValue >= 0.0 && newValue <= 1.0) {
widget.onChanged(newValue);
}
newValue = details.localPosition.dx / (constraints.maxWidth);
if (widget.divisions != null) newValue = (newValue / divident).round() * divident;
if (newValue >= 0.0 && newValue <= 1.0) widget.onChanged(newValue);
},
child: CustomPaint(
painter: _SliderPainter(
Expand All @@ -64,6 +69,7 @@ class _ZenitSliderState extends State<ZenitSlider> {
hoverColor: Theme.of(context).colorScheme.onSurface.withOpacity(0.05),
outlineColor: sliderTheme.outlineColor,
value: widget.value,
divisions: widget.divisions,
),
size: Size(constraints.maxWidth, 48),
),
Expand All @@ -83,6 +89,7 @@ class _SliderPainter extends CustomPainter {
final Color hoverColor;
final Color thumbColor;
final Color outlineColor;
final int? divisions;

_SliderPainter({
required this.trackColor,
Expand All @@ -92,6 +99,7 @@ class _SliderPainter extends CustomPainter {
required this.hoverColor,
required this.thumbColor,
required this.outlineColor,
this.divisions,
});

@override
Expand All @@ -113,25 +121,49 @@ class _SliderPainter extends CustomPainter {
..style = PaintingStyle.stroke
..strokeWidth = 1;

final RRect track = RRect.fromLTRBR(0.0, 12.0, size.width, size.height - 12, const Radius.circular(12.0));
final RRect active = RRect.fromLTRBR(
0.0,
12.0,
(size.width * value) > 24 ? (size.width * value) : 24.0,
size.height - 12.0,
const Radius.circular(12.0),
);
final Paint dividerPaint = Paint()
..color = outlineColor
..style = PaintingStyle.fill;

final Offset thumbPosition = Offset(
(size.width * value) > 24 ? (size.width * value) - ((size.height - 26) / 3) - 6 : 24 - 12,
size.height / 2,
);
double activeWidth() {
if (size.width * value >= size.width) {
return size.width;
} else if (size.width * value < 24) {
return 24;
} else {
return size.width * value + 12;
}
}

double thumbPositionX() {
if (size.width * value >= size.width) {
return size.width - 12;
} else if (size.width * value < 24) {
return 12;
} else {
return size.width * value;
}
}

const kTrackBorderRadius = Radius.circular(12.0);

final RRect track = RRect.fromLTRBR(0.0, 12.0, size.width, size.height - 12, kTrackBorderRadius);
final RRect active = RRect.fromLTRBR(0.0, 12.0, activeWidth(), size.height - 12.0, kTrackBorderRadius);

final Offset thumbPosition = Offset(thumbPositionX(), size.height / 2);

canvas.drawRRect(track, trackPaint);
canvas.drawRRect(track, outlinePaint);

canvas.drawRRect(active, activePaint);

final int divisions = this.divisions ?? 1;
for (int i = 0; i < divisions - 1; i++) {
final double x = (size.width / divisions) * i + (size.width / divisions);
final Offset position = Offset(x, size.height / 2);
canvas.drawCircle(position, 2, dividerPaint);
}

if (hover) {
final Paint hoverPaint = Paint()
..color = hoverColor
Expand All @@ -151,6 +183,7 @@ class _SliderPainter extends CustomPainter {
old.hover != hover ||
old.hoverColor != hoverColor ||
old.thumbColor != thumbColor ||
old.outlineColor != outlineColor;
old.outlineColor != outlineColor ||
old.divisions != divisions;
}
}

0 comments on commit 5fab511

Please sign in to comment.