Skip to content

Instantly share code, notes, and snippets.

@MaherSafadii
Last active June 6, 2025 20:16
Show Gist options
  • Save MaherSafadii/5bcd5848cd24442c8c91b1ef173ba73d to your computer and use it in GitHub Desktop.
Save MaherSafadii/5bcd5848cd24442c8c91b1ef173ba73d to your computer and use it in GitHub Desktop.
Flutter Cupertino Example
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:native_ios_dialog/native_ios_dialog.dart';
import 'package:pull_down_button/pull_down_button.dart';
ValueNotifier<Brightness> brightness = ValueNotifier(Brightness.light);
ValueNotifier<Color> accentColor = ValueNotifier(CupertinoColors.activeBlue);
void main() {
runApp(MainApp());
}
class MainApp extends StatefulWidget {
const MainApp({super.key});
@override
State<MainApp> createState() => _MainAppState();
}
class _MainAppState extends State<MainApp> {
@override
Widget build(BuildContext context) {
return ListenableBuilder(
listenable: Listenable.merge([brightness, accentColor]),
builder: (context, child) {
return CupertinoApp(
localizationsDelegates: const [
DefaultCupertinoLocalizations.delegate,
DefaultWidgetsLocalizations.delegate,
DefaultMaterialLocalizations.delegate,
],
debugShowCheckedModeBanner: false,
home: ComposeCupertinoReplica(),
theme: CupertinoThemeData(
brightness: brightness.value,
primaryColor: accentColor.value,
scaffoldBackgroundColor: CupertinoColors.systemGroupedBackground.resolveFrom(context),
),
);
},
);
}
}
class ComposeCupertinoReplica extends StatefulWidget {
const ComposeCupertinoReplica({super.key});
@override
State<ComposeCupertinoReplica> createState() => _ComposeCupertinoReplicaState();
}
class _ComposeCupertinoReplicaState extends State<ComposeCupertinoReplica> {
TextDirection layoutDirection = TextDirection.ltr;
bool checkboxValue1 = true;
bool checkboxValue2 = false;
bool? checkboxValue3 = true;
double slider1Value = 0.5;
double slider2Value = 0;
int pickerValue = 0;
@override
Widget build(BuildContext context) {
return Directionality(
textDirection: layoutDirection,
child: CupertinoTabScaffold(
backgroundColor: CupertinoColors.systemGroupedBackground.resolveFrom(context),
tabBar: CupertinoTabBar(
items: [
BottomNavigationBarItem(icon: Icon(CupertinoIcons.person_fill), label: 'Profile'),
BottomNavigationBarItem(icon: Icon(CupertinoIcons.settings), label: 'Settings'),
],
),
tabBuilder: (context, index) {
return CupertinoPageScaffold(
child: CustomScrollView(
slivers: [
CupertinoSliverNavigationBar.search(
automaticallyImplyLeading: false,
stretch: true,
largeTitle: Text('Cupertino'),
trailing: CupertinoButton(
padding: EdgeInsets.all(8),
onPressed: () {
setState(() {
brightness.value = brightness.value == Brightness.light ? Brightness.dark : Brightness.light;
});
},
child: Icon(CupertinoIcons.moon_stars, size: 30),
),
),
SliverSafeArea(
top: false,
sliver: SliverList.list(
children: [
CupertinoListSection.insetGrouped(
children: [
CupertinoListTile(
title: Text('Toggle layout direction'),
trailing: CupertinoSwitch(
value: layoutDirection == TextDirection.rtl,
onChanged: (v) {
setState(() {
layoutDirection = v ? TextDirection.rtl : TextDirection.ltr;
});
},
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 8),
child: Row(
spacing: 12,
children: [
CupertinoButton.tinted(
color: CupertinoColors.activeBlue,
padding: EdgeInsets.all(7),
borderRadius: BorderRadius.circular(99),
onPressed: () {
setState(() {
accentColor.value = CupertinoColors.activeBlue;
});
},
child: Icon(Icons.color_lens_outlined, size: 30, color: CupertinoColors.activeBlue),
),
CupertinoButton.tinted(
color: CupertinoColors.systemGreen,
padding: EdgeInsets.all(7),
borderRadius: BorderRadius.circular(99),
onPressed: () {
setState(() {
accentColor.value = CupertinoColors.systemGreen;
});
},
child: Icon(Icons.color_lens_outlined, size: 30, color: CupertinoColors.systemGreen),
),
CupertinoButton.tinted(
color: CupertinoColors.systemPurple,
padding: EdgeInsets.all(7),
borderRadius: BorderRadius.circular(99),
onPressed: () {
setState(() {
accentColor.value = CupertinoColors.systemPurple;
});
},
child: Icon(Icons.color_lens_outlined, size: 30, color: CupertinoColors.systemPurple),
),
CupertinoButton.tinted(
color: CupertinoColors.systemOrange,
padding: EdgeInsets.all(7),
borderRadius: BorderRadius.circular(99),
onPressed: () {
setState(() {
accentColor.value = CupertinoColors.systemOrange;
});
},
child: Icon(Icons.color_lens_outlined, size: 30, color: CupertinoColors.systemOrange),
),
CupertinoButton.tinted(
color: CupertinoColors.systemRed,
padding: EdgeInsets.all(7),
borderRadius: BorderRadius.circular(99),
onPressed: () {
setState(() {
accentColor.value = CupertinoColors.systemRed;
});
},
child: Icon(Icons.color_lens_outlined, size: 30, color: CupertinoColors.systemRed),
),
],
),
),
],
),
CupertinoListSection.insetGrouped(
children: [
CupertinoListTile.notched(
title: Text('SF Symbols'),
leadingSize: 33,
leading: Container(
width: 33,
height: 33,
decoration: BoxDecoration(
color: CupertinoColors.systemRed.resolveFrom(context),
borderRadius: BorderRadius.circular(8),
),
child: Icon(CupertinoIcons.heart, color: CupertinoColors.white),
),
trailing: Row(
spacing: 5,
children: [
Text('One', style: TextStyle(color: CupertinoColors.secondaryLabel.resolveFrom(context))),
CupertinoListTileChevron(),
],
),
),
CupertinoListTile.notched(
title: Text('Sections'),
leadingSize: 33,
leading: Container(
width: 33,
height: 33,
decoration: BoxDecoration(
color: CupertinoColors.systemIndigo.resolveFrom(context),
borderRadius: BorderRadius.circular(8),
),
child: Icon(CupertinoIcons.rectangle_grid_1x2, color: CupertinoColors.white),
),
trailing: Row(
spacing: 5,
children: [
Text('Two', style: TextStyle(color: CupertinoColors.secondaryLabel.resolveFrom(context))),
CupertinoListTileChevron(),
],
),
),
CupertinoListTile.notched(
title: Text('Adaptive widgets'),
leadingSize: 33,
leading: Container(
width: 33,
height: 33,
decoration: BoxDecoration(
color: CupertinoColors.systemBlue.resolveFrom(context),
borderRadius: BorderRadius.circular(8),
),
child: Icon(CupertinoIcons.device_phone_portrait, color: CupertinoColors.white),
),
trailing: Row(
spacing: 5,
children: [
Text(
'Three',
style: TextStyle(color: CupertinoColors.secondaryLabel.resolveFrom(context)),
),
CupertinoListTileChevron(),
],
),
),
CupertinoListTile.notched(
onTap: () {
showCupertinoSheet(
context: context,
pageBuilder:
(context) => CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
transitionBetweenRoutes: false,
middle: Text('Sheet'),
),
child: Center(child: Text('Sheet')),
),
);
},
title: Text('Bottom sheet'),
leadingSize: 33,
leading: Container(
width: 33,
height: 33,
decoration: BoxDecoration(
color: CupertinoColors.systemCyan.resolveFrom(context),
borderRadius: BorderRadius.circular(8),
),
child: Icon(CupertinoIcons.slider_horizontal_below_rectangle, color: CupertinoColors.white),
),
trailing: Row(
spacing: 5,
children: [
Text('Four', style: TextStyle(color: CupertinoColors.secondaryLabel.resolveFrom(context))),
CupertinoListTileChevron(),
],
),
),
],
),
CupertinoListSection.insetGrouped(
children: [
CupertinoListTile(
title: Text('Swipe horizontally'),
padding: EdgeInsets.symmetric(horizontal: 25, vertical: 20),
),
CupertinoListTile(
title: Text('Swipe horizontally'),
padding: EdgeInsets.symmetric(horizontal: 25, vertical: 20),
),
],
),
CupertinoListSection.insetGrouped(
header: Text('Controls'),
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 0, vertical: 9),
child: Row(
spacing: 10,
children: [
CupertinoCheckbox(
value: checkboxValue1,
onChanged: (v) {
setState(() {
checkboxValue1 = v!;
});
},
),
CupertinoCheckbox(
value: checkboxValue2,
onChanged: (v) {
setState(() {
checkboxValue2 = v!;
});
},
),
// CupertinoCheckbox(
// tristate: true,
// value: checkboxValue3,
// onChanged: (v) {
// setState(() {
// checkboxValue3 = v;
// });
// },
// ),
CupertinoButton(
padding: EdgeInsets.zero,
onPressed: () {},
child: Icon(CupertinoIcons.share, size: 30),
),
CupertinoButton.tinted(
padding: EdgeInsets.zero,
borderRadius: BorderRadius.circular(99),
onPressed: () {},
child: Icon(CupertinoIcons.plus, size: 30),
),
CupertinoButton.tinted(
color: CupertinoColors.systemFill.resolveFrom(context),
padding: EdgeInsets.zero,
borderRadius: BorderRadius.circular(99),
onPressed: () {},
child: Icon(CupertinoIcons.settings, size: 30),
),
CupertinoButton(
padding: EdgeInsets.zero,
onPressed: null,
child: Icon(CupertinoIcons.plus, size: 30),
),
],
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 9),
child: Row(
// mainAxisSize: MainAxisSize.min,
spacing: 15,
children: [
CupertinoButton.tinted(
color: CupertinoColors.systemGrey.resolveFrom(context),
sizeStyle: CupertinoButtonSize.small,
child: Text('Gray S'),
onPressed: () {},
),
CupertinoButton.tinted(
sizeStyle: CupertinoButtonSize.medium,
child: Text('Tinted M'),
onPressed: () {},
),
CupertinoButton.filled(
sizeStyle: CupertinoButtonSize.large,
child: Text('Filled L'),
onPressed: () {},
),
],
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 3),
child: Row(
// mainAxisSize: MainAxisSize.min,
// spacing: 15,
children: [
CupertinoButton(child: Text('Plain'), onPressed: () {}),
CupertinoButton(onPressed: null, child: Text('Disabled')),
CupertinoButton.filled(
sizeStyle: CupertinoButtonSize.medium,
onPressed: null,
child: Text('Disabled'),
),
],
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 5),
child: Row(
spacing: 10,
children: [
CupertinoSwitch(
value: checkboxValue1,
onChanged: (v) {
setState(() {
checkboxValue1 = v;
});
},
),
CupertinoSwitch(
value: checkboxValue2,
onChanged: (v) {
setState(() {
checkboxValue2 = v;
});
},
),
CupertinoSwitch(
value: checkboxValue1,
onChanged: (v) {
setState(() {
checkboxValue1 = v;
});
},
),
CupertinoSwitch(
value: checkboxValue2,
onChanged: (v) {
setState(() {
checkboxValue2 = v;
});
},
),
CupertinoActivityIndicator(radius: 14),
],
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 3),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Expanded(
child: Padding(
padding: const EdgeInsetsDirectional.only(end: 18),
child: CupertinoSlider(
value: slider1Value,
min: 0,
max: 1,
onChanged: (v) {
slider1Value = v;
setState(() {});
},
),
),
),
CupertinoActivityIndicator.partiallyRevealed(progress: slider1Value, radius: 14),
],
),
),
CupertinoTextField.borderless(
placeholder: 'Text field...',
padding: EdgeInsets.symmetric(horizontal: 24, vertical: 14),
),
Padding(
padding: const EdgeInsets.all(9),
child: CupertinoTextField(
placeholder: 'Text field...',
prefix: Padding(
padding: const EdgeInsetsDirectional.only(start: 5),
child: Icon(
CupertinoIcons.smiley,
color: CupertinoColors.secondaryLabel.resolveFrom(context),
),
),
suffix: Padding(
padding: const EdgeInsetsDirectional.only(end: 5),
child: Icon(
CupertinoIcons.paperclip,
color: CupertinoColors.secondaryLabel.resolveFrom(context),
),
),
decoration: BoxDecoration(
border: Border.all(color: CupertinoColors.systemFill.resolveFrom(context)),
borderRadius: BorderRadius.circular(99),
),
),
),
],
),
CupertinoListSection.insetGrouped(
header: Text('Popups'),
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 9),
child: Row(
spacing: 13,
children: [
CupertinoButton.tinted(
sizeStyle: CupertinoButtonSize.medium,
child: Text('Alert'),
onPressed: () {
showCupertinoDialog(
context: context,
builder:
(context) => CupertinoAlertDialog(
title: Text('Alert dialog'),
content: Text('Alert dialog content'),
actions: [
CupertinoDialogAction(
isDestructiveAction: true,
onPressed: () {
Navigator.pop(context);
},
child: Text('Cancel'),
),
CupertinoDialogAction(
child: Text('Ok'),
onPressed: () {
Navigator.pop(context);
},
),
],
),
);
},
),
CupertinoButton.tinted(
sizeStyle: CupertinoButtonSize.medium,
child: Text('Native'),
onPressed: () {
NativeIosDialog(
title: "Alert dialog",
message: "Alert dialog content",
// style: style,
actions: [
NativeIosDialogAction(
text: "Cancel",
style: NativeIosDialogActionStyle.destructive,
onPressed: () {},
),
NativeIosDialogAction(
text: "Ok",
style: NativeIosDialogActionStyle.defaultStyle,
onPressed: () {},
),
],
).show();
},
),
],
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 9),
child: Row(
spacing: 13,
children: [
CupertinoButton.tinted(
sizeStyle: CupertinoButtonSize.medium,
child: Text('Action sheet'),
onPressed: () {
showCupertinoModalPopup(
context: context,
builder:
(context) => CupertinoActionSheet(
title: Text('Action sheet'),
message: Text('This is the message of the action sheet'),
actions: [
CupertinoActionSheetAction(
onPressed: () {
Navigator.pop(context);
},
child: Text('Ok'),
),
CupertinoActionSheetAction(
onPressed: () {
Navigator.pop(context);
},
isDestructiveAction: true,
child: Text('Delete'),
),
],
cancelButton: CupertinoActionSheetAction(
onPressed: () {
Navigator.pop(context);
},
isDefaultAction: true,
child: Text('Cancel'),
),
),
);
},
),
CupertinoButton.tinted(
sizeStyle: CupertinoButtonSize.medium,
child: Text('Native'),
onPressed: () {
NativeIosDialog(
title: 'Action sheet',
message: 'This is the message of the action sheet',
style: NativeIosDialogStyle.actionSheet,
actions: [
NativeIosDialogAction(
text: 'Ok',
style: NativeIosDialogActionStyle.defaultStyle,
onPressed: () {},
),
NativeIosDialogAction(
text: 'Delete',
style: NativeIosDialogActionStyle.destructive,
onPressed: () {},
),
NativeIosDialogAction(
text: "Cancel",
style: NativeIosDialogActionStyle.cancel,
onPressed: () {},
),
],
).show();
},
),
],
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 9),
child: Row(
spacing: 13,
children: [
PullDownButton(
itemBuilder:
(context) => [
PullDownMenuTitle(title: Text('Menu')),
PullDownMenuItem(title: 'Share', icon: CupertinoIcons.share, onTap: () {}),
PullDownMenuItem(
title: 'Add to favourites',
icon: CupertinoIcons.bookmark,
onTap: null,
),
PullDownMenuDivider.large(),
PullDownMenuItem(
title: 'Delete',
icon: CupertinoIcons.trash,
isDestructive: true,
onTap: () {},
),
],
buttonBuilder:
(context, showMenu) => CupertinoButton.tinted(
sizeStyle: CupertinoButtonSize.medium,
onPressed: showMenu,
child: Text('Menu'),
),
),
],
),
),
],
),
CupertinoListSection.insetGrouped(
header: Text('Wheel pickers'),
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 9),
child: Row(
children: [
Expanded(
child: CupertinoSlidingSegmentedControl(
proportionalWidth: true,
groupValue: pickerValue,
children: {
0: Text('Months'),
1: Text('Time'),
2: Text('Date'),
3: Text('Date & Time'),
},
onValueChanged: (v) {
setState(() {
pickerValue = v ?? 0;
});
},
),
),
],
),
),
// show the names of the months in the picker
if (pickerValue == 0)
SizedBox(
height: 230,
child: CupertinoPicker(
key: ValueKey('month_picker'),
itemExtent: 30,
squeeze: 1,
onSelectedItemChanged: (v) {},
children: [
for (var month in [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December',
])
Text(month),
],
),
),
if (pickerValue == 1)
SizedBox(
height: 230,
child: CupertinoDatePicker(
key: ValueKey('time_picker'),
onDateTimeChanged: (v) {},
mode: CupertinoDatePickerMode.time,
),
),
if (pickerValue == 2)
SizedBox(
height: 230,
child: CupertinoDatePicker(
key: ValueKey('date_picker'),
mode: CupertinoDatePickerMode.date,
onDateTimeChanged: (v) {},
),
),
if (pickerValue == 3)
SizedBox(
height: 230,
child: CupertinoDatePicker(
key: ValueKey('datetime_picker'),
mode: CupertinoDatePickerMode.dateAndTime,
onDateTimeChanged: (v) {},
),
),
],
),
],
),
),
],
),
);
},
),
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment