Widget _sliderShowcase(){
RxDouble value = 5.0.obs;
return RepaintBoundary(
child: Obx(()=> Column(
children: <Widget>[
ListTile(
dense: true,
title: Text('Slider stepped (${value.value.toStringAsFixed(0)})'),
subtitle: Slider(
max: 30,
divisions: 31,
label: value.toStringAsFixed(0),
value: value.value,
onChanged: (double newValue) {
value.value = newValue.roundToDouble();
},
),
),
ListTile(
dense: true,
title: Text('Slider continuous (${value.toStringAsFixed(2)})'),
subtitle: Slider(
max: 30,
label: value.toStringAsFixed(0),
value: value.value,
onChanged: (double newValue) {
value.value = newValue;
},
),
),
ListTile(
dense: true,
title:
Text('Slider stepped disabled (${value.toStringAsFixed(0)})'),
subtitle: Slider(
max: 30,
divisions: 31,
label: value.toStringAsFixed(0),
value: value.value,
onChanged: null,
),
),
ListTile(
dense: true,
title: Text(
'Slider continuous disabled (${value.toStringAsFixed(2)})'),
subtitle: Slider(
max: 30,
label: value.toStringAsFixed(0),
value: value.value,
onChanged: null,
),
),
],
),
),
);
}
Widget _rangeSliderShowcase(){
Rx<RangeValues> values = const RangeValues(5, 12).obs;
return RepaintBoundary(
child: Obx(
()=> Column(
children: <Widget>[
ListTile(
dense: true,
title: Text('RangeSlider stepped (${RangeLabels(
values.value.start.toStringAsFixed(0),
values.value.end.toStringAsFixed(0),
)})'),
subtitle: RangeSlider(
max: 30,
divisions: 31,
labels: RangeLabels(
values.value.start.toStringAsFixed(0),
values.value.end.toStringAsFixed(0),
),
values: values.value,
onChanged: (RangeValues newValues) {
values.value = RangeValues(
newValues.start.roundToDouble(),
newValues.end.roundToDouble(),
);
},
),
),
ListTile(
dense: true,
title: Text('RangeSlider continuous (${RangeLabels(
values.value.start.toStringAsFixed(2),
values.value.end.toStringAsFixed(2),
)})'),
subtitle: RangeSlider(
max: 30,
labels: RangeLabels(
values.value.start.toStringAsFixed(2),
values.value.end.toStringAsFixed(2),
),
values: values.value,
onChanged: (RangeValues newValues) {
values.value = newValues;
},
),
),
ListTile(
dense: true,
title: Text('RangeSlider stepped disabled (${RangeLabels(
values.value.start.toStringAsFixed(0),
values.value.end.toStringAsFixed(0),
)})'),
subtitle: RangeSlider(
max: 30,
divisions: 31,
labels: RangeLabels(
values.value.start.toStringAsFixed(0),
values.value.end.toStringAsFixed(0),
),
values: values.value,
onChanged: null,
),
),
ListTile(
dense: true,
title: Text('RangeSlider continuous disabled (${RangeLabels(
values.value.start.toStringAsFixed(2),
values.value.end.toStringAsFixed(2),
)})'),
subtitle: RangeSlider(
max: 30,
divisions: 31,
labels: RangeLabels(
values.value.start.toStringAsFixed(2),
values.value.end.toStringAsFixed(2),
),
values: values.value,
onChanged: null,
),
),
],
),
),
);
}
SliderThemeScreen.dart
class SliderThemeScreen extends StatefulWidget {
final bool showAppBar;
const SliderThemeScreen({super.key, this.showAppBar = false});
@override
State<SliderThemeScreen> createState() => _SliderThemeScreenState();
}
class _SliderThemeScreenState extends State<SliderThemeScreen> {
ThemeController themeController = Get.find();
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Theme.of(context).colorScheme.background,
appBar: widget.showAppBar
? AppBar(
title: const Text(
"Slider Theme",
),
)
: null,
body: Center(
child: Container(
constraints: const BoxConstraints(
maxWidth: 1000,
),
alignment: Alignment.topCenter,
padding: const EdgeInsets.all(16),
child: Stack(
alignment: Alignment.topCenter,
children: [
SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
const SizedBox(height: 75,),
_buildCommonContainer(
child: ThemeColorSelector(controller: themeController,),
title: "Theme Color",
description: "Select the theme mode you prefer.",
),
const ListTileReveal(
leading: Icon(Icons.tune_outlined),
title: Text('Slider'),
subtitleDense: true,
subtitle: Text(
"The Slider widget allows users to select a value from a continuous range by dragging a thumb along a track.\nIt's a fundamental component for adjusting settings or values in your app.\n Unlike the PopupMenuButton, which is primarily used for menu interactions, the Slider provides direct and intuitive control over a single value. \nConsider incorporating the Slider when you need precise user input for numeric values or settings.",
),
),
Obx(
() => CustomContainer(
title: 'Slider Main color',
description: 'Main color',
child: ThemePopupMenu3(
schemeIndex: themeController.sliderMainColorIndex.value,
onChanged: themeController.setSliderMainColorIndex),
),
),
const SizedBox(
height: 20,
),
Obx(
() => CustomContainer(
title: 'Slider Indicator color',
description: 'Indicator value color',
child: ThemePopupMenu3(
schemeIndex:
themeController.sliderIndicatorColorIndex.value,
onChanged:
themeController.setSliderIndicatorColorIndex),
),
),
Obx(
()=> SliderIndicatorPopupMenu(
title: const Text('Indicator type'),
labelForDefault: themeController.useMaterial3.value
? 'default M3 (drop)'
: 'default M2 (rectangular)',
index:
themeController.sliderValueIndicatorType?.value.index ??
-1,
onChanged: (int index) {
if (index < 0 ||
index >= FlexSliderIndicatorType.values.length) {
themeController.setSliderValueIndicatorType(null);
} else {
themeController.setSliderValueIndicatorType(
FlexSliderIndicatorType.values[index]);
}
},
),
),
Obx(
()=> SliderShowIndicatorPopupMenu(
title: const Text('Indicator visibility'),
labelForDefault: 'Default (Only for discrete)',
index: themeController.sliderShowValueIndicator?.value.index ?? -1,
onChanged: (int index) {
if (index < 0 || index >= ShowValueIndicator.values.length) {
themeController.setSliderShowValueIndicator(null);
} else {
themeController.setSliderShowValueIndicator(
ShowValueIndicator.values[index]);
}
},
),
),
const SizedBox(height: 20),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Obx(
()=> Flexible(
child: _buildCommonContainer(
child: SliderTheme(
data: SliderTheme.of(context).copyWith(
overlayShape: SliderComponentShape.noOverlay,
),
child: SizedBox(
width: 1000,
child: Slider(
value: themeController
.sliderTrackerHeight.value,
min: 0,
max: 14,
divisions: 15,
inactiveColor: Colors.transparent,
onChanged: (double value) {
themeController
.setSliderTrackerHeight(value);
if (kDebugMode) {
print(value);
}
},
),
),
),
title: 'Slider Track height',
description:
'Adjust the slider track height to your preference.',
),
),
),
Padding(
padding: const EdgeInsets.only(left: 10.0, top: 28),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
const Text('Height'),
Obx(
() {
final borderRadius = themeController
.sliderTrackerHeight.value;
final integerPart = double.parse(
borderRadius.toStringAsFixed(0))
.toInt();
return SizedBox(
width: 55,
child: Text(
textAlign: TextAlign.center,
maxLines: 2,
softWrap: true,
themeController.sliderTrackerHeight
.value ==
0
? 'default height'
: integerPart.toString(),
style: TextStyles.titleSmall
.copyWith(fontSize: 12),
),
);
},
),
],
),
)
],
),
const SizedBox(height: 20,),
const Divider(),
const ListTile(title: Text('Slider')),
_sliderShowcase(),
const SizedBox(height: 20,),
const Divider(),
const ListTile(title: Text('Range Slider')),
_rangeSliderShowcase(),
],
),
),
Container(
height:70,
width: double.infinity,
color: Theme.of(context).colorScheme.background,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Slider(
max: 30,
divisions: 31,
label: '',
value: 15.0,
onChanged: (double newValue) {
},
),
const Divider(),
],
),
),]
),
),
)
);
}
Widget _buildCommonContainer(
{required Widget child,
required String title,
required String description}) {
return Column(
children: [
Container(
padding: const EdgeInsets.only(left: 16),
alignment: Alignment.centerLeft,
child: Text(
title,
style: TextStyles.titleSmall,
),
),
const SizedBox(height: 5),
Container(
width: double.infinity,
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Theme.of(context).scaffoldBackgroundColor,
borderRadius: BorderRadius.circular(10),
boxShadow: [containerShadow(context)],
),
child: child,
),
const SizedBox(height: 5),
Container(
padding: const EdgeInsets.only(left: 16),
alignment: Alignment.centerLeft,
child: Text(
description,
style: TextStyles.bodyMedium,
),
),
],
);
}
Widget _sliderShowcase(){
RxDouble value = 5.0.obs;
return RepaintBoundary(
child: Obx(()=> Column(
children: <Widget>[
ListTile(
dense: true,
title: Text('Slider stepped (${value.value.toStringAsFixed(0)})'),
subtitle: Slider(
max: 30,
divisions: 31,
label: value.toStringAsFixed(0),
value: value.value,
onChanged: (double newValue) {
value.value = newValue.roundToDouble();
},
),
),
ListTile(
dense: true,
title: Text('Slider continuous (${value.toStringAsFixed(2)})'),
subtitle: Slider(
max: 30,
label: value.toStringAsFixed(0),
value: value.value,
onChanged: (double newValue) {
value.value = newValue;
},
),
),
ListTile(
dense: true,
title:
Text('Slider stepped disabled (${value.toStringAsFixed(0)})'),
subtitle: Slider(
max: 30,
divisions: 31,
label: value.toStringAsFixed(0),
value: value.value,
onChanged: null,
),
),
ListTile(
dense: true,
title: Text(
'Slider continuous disabled (${value.toStringAsFixed(2)})'),
subtitle: Slider(
max: 30,
label: value.toStringAsFixed(0),
value: value.value,
onChanged: null,
),
),
],
),
),
);
}
Widget _rangeSliderShowcase(){
Rx<RangeValues> values = const RangeValues(5, 12).obs;
return RepaintBoundary(
child: Obx(
()=> Column(
children: <Widget>[
ListTile(
dense: true,
title: Text('RangeSlider stepped (${RangeLabels(
values.value.start.toStringAsFixed(0),
values.value.end.toStringAsFixed(0),
)})'),
subtitle: RangeSlider(
max: 30,
divisions: 31,
labels: RangeLabels(
values.value.start.toStringAsFixed(0),
values.value.end.toStringAsFixed(0),
),
values: values.value,
onChanged: (RangeValues newValues) {
values.value = RangeValues(
newValues.start.roundToDouble(),
newValues.end.roundToDouble(),
);
},
),
),
ListTile(
dense: true,
title: Text('RangeSlider continuous (${RangeLabels(
values.value.start.toStringAsFixed(2),
values.value.end.toStringAsFixed(2),
)})'),
subtitle: RangeSlider(
max: 30,
labels: RangeLabels(
values.value.start.toStringAsFixed(2),
values.value.end.toStringAsFixed(2),
),
values: values.value,
onChanged: (RangeValues newValues) {
values.value = newValues;
},
),
),
ListTile(
dense: true,
title: Text('RangeSlider stepped disabled (${RangeLabels(
values.value.start.toStringAsFixed(0),
values.value.end.toStringAsFixed(0),
)})'),
subtitle: RangeSlider(
max: 30,
divisions: 31,
labels: RangeLabels(
values.value.start.toStringAsFixed(0),
values.value.end.toStringAsFixed(0),
),
values: values.value,
onChanged: null,
),
),
ListTile(
dense: true,
title: Text('RangeSlider continuous disabled (${RangeLabels(
values.value.start.toStringAsFixed(2),
values.value.end.toStringAsFixed(2),
)})'),
subtitle: RangeSlider(
max: 30,
divisions: 31,
labels: RangeLabels(
values.value.start.toStringAsFixed(2),
values.value.end.toStringAsFixed(2),
),
values: values.value,
onChanged: null,
),
),
],
),
),
);
}
}