Widget _popupMenuButtonsShowcase() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
children: <Widget>[
_popupMenuButtonShowcase(),
const SizedBox(width: 16),
_checkedPopupMenuButtonShowcase(),
const SizedBox(width: 16),
_popupMenuButtonTilesShowcase(),
],
),
]);
}
Widget _popupMenuButtonShowcase () {
return RepaintBoundary(
child: PopupMenuButton<int>(
onSelected: (_) {},
position: PopupMenuPosition.under,
itemBuilder: (BuildContext context) => const <PopupMenuItem<int>>[
PopupMenuItem<int>(value: 1, child: Text('Option 1')),
PopupMenuItem<int>(value: 2, child: Text('Option 2')),
PopupMenuItem<int>(value: 3, child: Text('Option 3')),
PopupMenuItem<int>(value: 4, child: Text('Option 4')),
PopupMenuItem<int>(value: 5, child: Text('Option 5')),
],
icon: const Icon(Icons.more_vert),
),
);
}
Widget _checkedPopupMenuButtonShowcase(){
return RepaintBoundary(
child: PopupMenuButton<int>(
onSelected: (_) {},
position: PopupMenuPosition.under,
itemBuilder: (BuildContext context) => const <PopupMenuItem<int>>[
CheckedPopupMenuItem<int>(value: 1, child: Text('Option 1')),
CheckedPopupMenuItem<int>(value: 2, child: Text('Option 2')),
CheckedPopupMenuItem<int>(value: 3, child: Text('Option 3')),
CheckedPopupMenuItem<int>(value: 4, child: Text('Option 4')),
CheckedPopupMenuItem<int>(value: 5, child: Text('Option 5')),
],
icon: const Icon(Icons.playlist_add_check),
),
);
}
Widget _popupMenuButtonTilesShowcase(){
return RepaintBoundary(
child: PopupMenuButton<int>(
tooltip: 'Show menu using\nListTile items',
onSelected: (_) {},
position: PopupMenuPosition.under,
itemBuilder: (BuildContext context) => const <PopupMenuItem<int>>[
PopupMenuItem<int>(
value: 1,
child:
ListTile(leading: Icon(Icons.alarm), title: Text('Alarm'))),
PopupMenuItem<int>(
value: 2,
child: ListTile(
leading: Icon(Icons.cabin), title: Text('Wood cabin'))),
PopupMenuItem<int>(
value: 3,
child: ListTile(
leading: Icon(Icons.camera_outdoor_rounded),
title: Text('Surveillance'))),
PopupMenuItem<int>(
value: 4,
child: ListTile(
leading: Icon(Icons.water_damage),
title: Text('Water damage'))),
],
icon: const Icon(Icons.more_horiz),
),
);
}
PopupScreen.dart
class PopupScreen extends StatefulWidget {
final bool showAppBar;
const PopupScreen({super.key, this.showAppBar = false});
@override
State<PopupScreen> createState() => _PopupScreenState();
}
class _PopupScreenState extends State<PopupScreen> {
ThemeController themeController = Get.find();
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Theme.of(context).colorScheme.background,
appBar: widget.showAppBar
? AppBar(
title: const Text(
"Popup & Dropdown Theme",
),
)
: null,
body: Center(
child: Container(
constraints: const BoxConstraints(
maxWidth: 1000,
),
alignment: Alignment.topCenter,
padding: const EdgeInsets.all(16),
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
_buildCommonContainer(
child: ThemeColorSelector(controller: themeController,),
title: "Theme Color",
description: "Select the theme mode you prefer.",
),
const ListTileReveal(
leading: Icon(Icons.arrow_drop_down_circle_outlined),
title: Text('Popup Menu Button'),
subtitleDense: true,
subtitle: Text(
'The PopupMenuButton can be used on any widget, it is typically '
'used on an Icon, as below. Its implementation differs from newer '
'Material-3 menu components. '
'PopupMenuButton is originally a Material-2 design, that has also '
'been updated to M3 style. It still works well and can be themed '
'to a certain degree. '
'If applicable, consider using newer more versatile M3 menu '
'components, like MenuAnchor and DropdownMenu.\n',
),
),
_popupMenuButtonsShowcase(),
const SizedBox(height: 20,),
Obx(
() => CustomContainer(
title: 'Popupmenu Icon color',
description: 'Icon color',
child: ThemePopupMenu3(
schemeIndex: themeController.popupMenuIconColorIndex.value,
onChanged: themeController.setPopupMenuIconColor),
),
),
const SizedBox(
height: 20,
),
const SizedBox(
height: 10,
),
Obx(
() => CustomContainer(
title: 'Popupmenu Container color',
description: 'Background color',
child: ThemePopupMenu3(
schemeIndex:
themeController.popupMenuContainerColorIndex.value,
onChanged: themeController.setPopupMenuContainerColor),
),
),
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
.popupMenuContainerColorOpacity.value,
min: -1,
max: 100,
divisions: 25,
inactiveColor: Colors.transparent,
onChanged: (double value) {
themeController
.setPopupMenuContainerColorOpacity(value);
if (kDebugMode) {
print(value);
}
},
),
),
),
title: 'Popupmenu Container Color Opacity',
description:
'Adjust the popupmenu container color opacity to your preference.',
),
),
),
Padding(
padding: const EdgeInsets.only(left: 10.0, top: 28),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
const Text('Opacity'),
Obx(
() {
final borderRadius = themeController
.popupMenuContainerColorOpacity.value;
final integerPart =
double.parse(borderRadius.toStringAsFixed(0))
.toInt();
return SizedBox(
width: 55,
child: Text(
textAlign: TextAlign.center,
maxLines: 2,
softWrap: true,
themeController
.popupMenuContainerColorOpacity.value ==
-1
? 'default opacity'
: integerPart.toString(),
style: TextStyles.titleSmall
.copyWith(fontSize: 12),
),
);
},
)
],
),
)
],
),
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
.popupMenuContainerRadius.value,
min: 0,
max: 12,
divisions: 10,
inactiveColor: Colors.transparent,
onChanged: (double value) {
themeController
.setPopupMenuContainerRadius(value);
if (kDebugMode) {
print(value);
}
},
),
),
),
title: 'Popupmenu Container Radius',
description:
'Adjust the popupmenu container radius to your preference.',
),
),
),
Padding(
padding: const EdgeInsets.only(left: 10.0, top: 28),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
const Text('Radius'),
Obx(
() {
final borderRadius = themeController
.popupMenuContainerRadius.value;
final integerPart =
double.parse(borderRadius.toStringAsFixed(0))
.toInt();
return SizedBox(
width: 55,
child: Text(
textAlign: TextAlign.center,
maxLines: 2,
softWrap: true,
themeController
.popupMenuContainerRadius.value <=0? 'default Radius'
: integerPart.toString(),
style: TextStyles.titleSmall
.copyWith(fontSize: 12),
),
);
},
)
],
),
)
],
),
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
.popupMenuElevation.value,
min: 0,
max: 20,
divisions: 11,
inactiveColor: Colors.transparent,
onChanged: (double value) {
themeController
.setPopupMenuElevation(value);
if (kDebugMode) {
print(value);
}
},
),
),
),
title: 'Popupmenu Elevation',
description:
'Adjust the popupmenu elevation opacity to your preference.',
),
),
),
Padding(
padding: const EdgeInsets.only(left: 10.0, top: 28),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
const Text('ELEV'),
Obx(
() {
final elevation = themeController
.popupMenuElevation.value;
final integerPart =
double.parse(elevation.toStringAsFixed(0))
.toInt();
return SizedBox(
width: 55,
child: Text(
textAlign: TextAlign.center,
maxLines: 2,
softWrap: true,
themeController
.popupMenuElevation.value <=0
? 'default elev'
: integerPart.toString(),
style: TextStyles.titleSmall
.copyWith(fontSize: 12),
),
);
},
)
],
),
)
],
),
const SizedBox(height: 20,),
],
),
),
),
),
);
}
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 _popupMenuButtonsShowcase() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
children: <Widget>[
_popupMenuButtonShowcase(),
const SizedBox(width: 16),
_checkedPopupMenuButtonShowcase(),
const SizedBox(width: 16),
_popupMenuButtonTilesShowcase(),
],
),
]);
}
Widget _popupMenuButtonShowcase () {
return RepaintBoundary(
child: PopupMenuButton<int>(
onSelected: (_) {},
position: PopupMenuPosition.under,
itemBuilder: (BuildContext context) => const <PopupMenuItem<int>>[
PopupMenuItem<int>(value: 1, child: Text('Option 1')),
PopupMenuItem<int>(value: 2, child: Text('Option 2')),
PopupMenuItem<int>(value: 3, child: Text('Option 3')),
PopupMenuItem<int>(value: 4, child: Text('Option 4')),
PopupMenuItem<int>(value: 5, child: Text('Option 5')),
],
icon: const Icon(Icons.more_vert),
),
);
}
Widget _checkedPopupMenuButtonShowcase(){
return RepaintBoundary(
child: PopupMenuButton<int>(
onSelected: (_) {},
position: PopupMenuPosition.under,
itemBuilder: (BuildContext context) => const <PopupMenuItem<int>>[
CheckedPopupMenuItem<int>(value: 1, child: Text('Option 1')),
CheckedPopupMenuItem<int>(value: 2, child: Text('Option 2')),
CheckedPopupMenuItem<int>(value: 3, child: Text('Option 3')),
CheckedPopupMenuItem<int>(value: 4, child: Text('Option 4')),
CheckedPopupMenuItem<int>(value: 5, child: Text('Option 5')),
],
icon: const Icon(Icons.playlist_add_check),
),
);
}
Widget _popupMenuButtonTilesShowcase(){
return RepaintBoundary(
child: PopupMenuButton<int>(
tooltip: 'Show menu using\nListTile items',
onSelected: (_) {},
position: PopupMenuPosition.under,
itemBuilder: (BuildContext context) => const <PopupMenuItem<int>>[
PopupMenuItem<int>(
value: 1,
child:
ListTile(leading: Icon(Icons.alarm), title: Text('Alarm'))),
PopupMenuItem<int>(
value: 2,
child: ListTile(
leading: Icon(Icons.cabin), title: Text('Wood cabin'))),
PopupMenuItem<int>(
value: 3,
child: ListTile(
leading: Icon(Icons.camera_outdoor_rounded),
title: Text('Surveillance'))),
PopupMenuItem<int>(
value: 4,
child: ListTile(
leading: Icon(Icons.water_damage),
title: Text('Water damage'))),
],
icon: const Icon(Icons.more_horiz),
),
);
}
}