I'm having problems creating a custom slider on flutter. The image is the following one:
CodePudding user response:
You'd need to customize the shapes of Theme.sliderTheme.thumbShape
and Theme.sliderTheme.trackShape
.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Flutter Demo',
home: MyHomePage(),
debugShowCheckedModeBanner: false,
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
double sliderValue = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
color: Color.fromARGB(255, 255, 115, 0),
child: Theme(
data: Theme.of(context).copyWith(
sliderTheme: SliderThemeData(
thumbShape: SquareSliderComponentShape(),
trackShape: MyRoundedRectSliderTrackShape(),
),
),
child: Slider(
onChanged: (value) => setState(() => sliderValue = value),
value: sliderValue,
min: 0,
max: 100,
activeColor: Colors.black,
inactiveColor: const Color.fromARGB(255, 230, 209, 138),
),
),
),
),
);
}
}
class SquareSliderComponentShape extends SliderComponentShape {
@override
Size getPreferredSize(bool isEnabled, bool isDiscrete) {
return const Size(20, 30);
}
@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 canvas = context.canvas;
canvas.drawShadow(
Path()
..addRRect(RRect.fromRectAndRadius(
Rect.fromCenter(center: center, width: 24, height: 30),
const Radius.circular(4),
)),
Colors.black,
5,
false);
canvas.drawRRect(
RRect.fromRectAndRadius(
Rect.fromCenter(center: center, width: 20, height: 30),
const Radius.circular(4),
),
Paint()..color = Colors.amber,
);
}
}
class MyRoundedRectSliderTrackShape extends SliderTrackShape
with BaseSliderTrackShape {
const MyRoundedRectSliderTrackShape();
@override
void paint(
PaintingContext context,
Offset offset, {
required RenderBox parentBox,
required SliderThemeData sliderTheme,
required Animation<double> enableAnimation,
required TextDirection textDirection,
required Offset thumbCenter,
bool isDiscrete = false,
bool isEnabled = false,
double additionalTrackHeight = 10,
}) {
if (sliderTheme.trackHeight == null || sliderTheme.trackHeight! <= 0) {
return;
}
final ColorTween activeTrackColorTween = ColorTween(
begin: sliderTheme.disabledActiveTrackColor,
end: sliderTheme.activeTrackColor);
final ColorTween inactiveTrackColorTween = ColorTween(
begin: sliderTheme.disabledInactiveTrackColor,
end: sliderTheme.inactiveTrackColor);
final Paint activePaint = Paint()
..color = activeTrackColorTween.evaluate(enableAnimation)!;
final Paint inactivePaint = Paint()
..color = inactiveTrackColorTween.evaluate(enableAnimation)!;
final Paint leftTrackPaint;
final Paint rightTrackPaint;
switch (textDirection) {
case TextDirection.ltr:
leftTrackPaint = activePaint;
rightTrackPaint = inactivePaint;
break;
case TextDirection.rtl:
leftTrackPaint = inactivePaint;
rightTrackPaint = activePaint;
break;
}
final Rect trackRect = getPreferredRect(
parentBox: parentBox,
offset: offset,
sliderTheme: sliderTheme,
isEnabled: isEnabled,
isDiscrete: isDiscrete,
);
final Radius activeTrackRadius =
Radius.circular((trackRect.height additionalTrackHeight) / 2);
context.canvas.drawRRect(
RRect.fromLTRBAndCorners(
trackRect.left,
trackRect.top - (additionalTrackHeight / 2),
thumbCenter.dx,
trackRect.bottom (additionalTrackHeight / 2),
topLeft: activeTrackRadius,
bottomLeft: activeTrackRadius,
),
leftTrackPaint,
);
context.canvas.drawRRect(
RRect.fromLTRBAndCorners(
thumbCenter.dx,
trackRect.top - (additionalTrackHeight / 2),
trackRect.right,
trackRect.bottom (additionalTrackHeight / 2),
topRight: activeTrackRadius,
bottomRight: activeTrackRadius,
),
rightTrackPaint,
);
}
}