Skip to content

Instantly share code, notes, and snippets.

@TobiCrackIT
Created December 3, 2023 23:01
Show Gist options
  • Save TobiCrackIT/46aa1d2dc0ed8d4c0e5d0896a616650e to your computer and use it in GitHub Desktop.
Save TobiCrackIT/46aa1d2dc0ed8d4c0e5d0896a616650e to your computer and use it in GitHub Desktop.
Custom Range Slider
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
//colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
//useMaterial3: true,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
final String title;
const MyHomePage({
Key? key,
required this.title,
}) : super(key: key);
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
double _lowerValue = 10;
double _upperValue = 60;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SliderTheme(
data: SliderTheme.of(context).copyWith(
trackHeight: 20,
rangeTrackShape: SpecialTrackShape(),
thumbShape: const RoundSliderThumbShape(enabledThumbRadius: 30),
activeTickMarkColor: Colors.red,
inactiveTickMarkColor: Colors.blue,
activeTrackColor:Colors.green,
inactiveTrackColor:Colors.red,
overlayColor: Colors.green,
valueIndicatorShape: const PaddleSliderValueIndicatorShape(),
),
child: RangeSlider(
values: RangeValues(_lowerValue, _upperValue),
min: 0,
max: 100,
onChanged: (RangeValues value) {
setState(() {
_lowerValue = value.start;
_upperValue = value.end;
});
},
),
)
],
),
),
);
}
}
class SpecialTrackShape extends RectangularRangeSliderTrackShape {
@override
void paint(
PaintingContext context,
Offset offset, {
required RenderBox parentBox,
required SliderThemeData sliderTheme,
required Animation<double>? enableAnimation,
required Offset startThumbCenter,
required Offset endThumbCenter,
bool isEnabled = false,
bool isDiscrete = false,
required TextDirection textDirection,
}) {
assert(sliderTheme.disabledActiveTrackColor != null);
assert(sliderTheme.disabledInactiveTrackColor != null);
assert(sliderTheme.activeTrackColor != null);
assert(sliderTheme.inactiveTrackColor != null);
assert(sliderTheme.rangeThumbShape != null);
assert(enableAnimation != null);
// Assign the track segment paints, which are left: active, right: inactive,
// but reversed for right to left text.
final ColorTween activeTrackColorTween = ColorTween(
begin: sliderTheme.disabledActiveTrackColor,
end: sliderTheme.activeTrackColor);
final ColorTween inactiveTrackColorTween = ColorTween(
begin: sliderTheme.disabledInactiveTrackColor,
end: sliderTheme.inactiveTrackColor);
final ColorTween specialTrackColorTween = ColorTween(
begin: Colors.yellow,
end: Colors.yellow);
final Paint activePaint = Paint()
..color = activeTrackColorTween.evaluate(enableAnimation!)!;
final Paint inactivePaint = Paint()
..color = inactiveTrackColorTween.evaluate(enableAnimation)!;
final Paint specialPaint = Paint()
..color = specialTrackColorTween.evaluate(enableAnimation)!;
final Offset leftThumbOffset;
final Offset rightThumbOffset;
switch (textDirection) {
case TextDirection.ltr:
leftThumbOffset = startThumbCenter;
rightThumbOffset = endThumbCenter;
case TextDirection.rtl:
leftThumbOffset = endThumbCenter;
rightThumbOffset = startThumbCenter;
}
final Rect trackRect = getPreferredRect(
parentBox: parentBox,
offset: offset,
sliderTheme: sliderTheme,
isEnabled: isEnabled,
isDiscrete: isDiscrete,
);
final Rect leftTrackSegment = Rect.fromLTRB(
trackRect.left, trackRect.top, leftThumbOffset.dx, trackRect.bottom);
if (!leftTrackSegment.isEmpty) {
context.canvas.drawRect(leftTrackSegment, inactivePaint);
}
final Rect middleTrackSegment = Rect.fromLTRB(leftThumbOffset.dx,
trackRect.top, rightThumbOffset.dx, trackRect.bottom);
if (!middleTrackSegment.isEmpty) {
context.canvas.drawRect(middleTrackSegment, activePaint);
}
final Rect rightTrackSegment = Rect.fromLTRB(
rightThumbOffset.dx, trackRect.top, trackRect.right, trackRect.bottom);
if (!rightTrackSegment.isEmpty) {
context.canvas.drawRect(rightTrackSegment, specialPaint);
}
}
}
class CustomTrackShape extends RoundedRectSliderTrackShape {
@override
Rect getPreferredRect({
required RenderBox parentBox,
Offset offset = Offset.zero,
required SliderThemeData sliderTheme,
bool isEnabled = false,
bool isDiscrete = false,
}) {
final double trackHeight = sliderTheme.trackHeight!;
final double trackLeft = offset.dx;
final double trackTop =
offset.dy + (parentBox.size.height - trackHeight) / 2;
final double trackWidth = parentBox.size.width;
return Rect.fromLTWH(trackLeft, trackTop, trackWidth, trackHeight);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment