Last active
June 6, 2025 20:16
-
-
Save MaherSafadii/5bcd5848cd24442c8c91b1ef173ba73d to your computer and use it in GitHub Desktop.
Flutter Cupertino Example
This file contains hidden or 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
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