Created
December 3, 2023 23:01
-
-
Save TobiCrackIT/46aa1d2dc0ed8d4c0e5d0896a616650e to your computer and use it in GitHub Desktop.
Custom Range Slider
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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