-
-
Save Alexisvt/81e7ff61e1d95fa647b68f463bd530f1 to your computer and use it in GitHub Desktop.
Drop in file for flutter to show a whats new page for the user that is native for android and iOS. (Similar to apples version in keynote, pages, app store and other apps)
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/material.dart'; | |
import 'package:flutter/cupertino.dart'; | |
import 'dart:io'; | |
import 'dart:async'; | |
//Example | |
class StartPage extends StatelessWidget { | |
// SHow Native Pop Up to User | |
static Future<Null> showAlertPopup( | |
BuildContext context, String title, String detail) async { | |
void showDemoDialog<T>({BuildContext context, Widget child}) { | |
showDialog<T>( | |
context: context, | |
barrierDismissible: false, | |
builder: (BuildContext context) => child, | |
); | |
} | |
return showDemoDialog<Null>( | |
context: context, | |
child: NativeDialog( | |
title: title, | |
content: detail, | |
actions: <NativeDialogAction>[ | |
NativeDialogAction( | |
text: 'OK', | |
isDestructive: false, | |
onPressed: () { | |
Navigator.pop(context); | |
}), | |
], | |
)); | |
} | |
@override | |
Widget build(BuildContext context) { | |
// Create a List of WhatsNewItem for use in the Whats New Page | |
// Create as many as you need, it will be scrollable | |
List<ListTile> _items = [ | |
ListTile( | |
title: Text('Dart Theme'), //Title is the only Required Item | |
subtitle: Text('Black and grey theme'), | |
leading: Icon(Icons.color_lens), | |
onTap: () { | |
// You Can Navigate to Locations in the App | |
Navigator.of(context).pushNamed("/settings"); | |
}, | |
), | |
ListTile( | |
title: Text('Quick Send'), | |
subtitle: Text('Step by step guide for sending emails'), | |
leading: Icon(Icons.send), | |
onTap: () { | |
Navigator.of(context).pushNamed("/settings"); | |
}, | |
), | |
ListTile( | |
title: Text('Video List Layout'), | |
subtitle: Text('Choose between a Grid layout and List layout'), | |
leading: Icon(Icons.grid_on), | |
onTap: () { | |
Navigator.of(context).pushNamed("/settings"); | |
}, | |
), | |
ListTile( | |
title: Text('Thumbnail Management'), | |
subtitle: | |
Text('Edit and view the current video for any editable email'), | |
leading: Icon(Icons.color_lens), | |
onTap: () { | |
// You Can Show a Native Pop Up for Giving More Detail to the user | |
showAlertPopup(context, "Info", | |
"Select a video, go to the video details (bottom right icon), scroll down to the thumbnail tile."); | |
}, | |
), | |
]; | |
return new Scaffold( | |
body: SafeArea( | |
//Whats New Page is Just A Widget, Use in a Scaffold and SafeArea for Best Results | |
child: WhatsNewPage( | |
title: Text( | |
"What's New", | |
textAlign: TextAlign.center, | |
style: TextStyle( | |
// Text Style Needed to Look like iOS 11 | |
fontSize: 22.0, | |
fontWeight: FontWeight.bold, | |
), | |
), | |
buttonText: Text('Continue'), | |
items: _items, //Required | |
onPressed: () { | |
// If Showing from a login screen you will need to navigate to the next page | |
// If Showing from a menu you can Navigator.pop() | |
Navigator.of(context).pushNamed("/menu"); | |
}, | |
), | |
), | |
); | |
} | |
} | |
// Native Dialog | |
class WhatsNewPage extends StatefulWidget { | |
final Widget title; | |
final Widget buttonText; | |
final List<ListTile> items; | |
final VoidCallback onPressed; | |
WhatsNewPage({ | |
@required this.items, | |
@required this.title, | |
@required this.buttonText, | |
this.onPressed, | |
}); | |
@override | |
_WhatsNewPageState createState() => _WhatsNewPageState(); | |
} | |
class _WhatsNewPageState extends State<WhatsNewPage> { | |
@override | |
Widget build(BuildContext context) { | |
return (Scaffold( | |
body: SafeArea( | |
child: Stack( | |
fit: StackFit.loose, | |
children: <Widget>[ | |
Positioned( | |
top: 10.0, | |
left: 0.0, | |
right: 0.0, | |
child: widget.title, | |
), | |
Positioned( | |
left: 0.0, | |
right: 0.0, | |
top: 50.0, | |
bottom: 80.0, | |
child: SingleChildScrollView( | |
physics: AlwaysScrollableScrollPhysics(), | |
child: ListBody( | |
children: widget.items | |
.map( | |
(ListTile item) => ListTile( | |
title: item.title, | |
subtitle: item.subtitle, | |
leading: item.leading, | |
trailing: item.trailing, | |
onTap: item.onTap, | |
onLongPress: item.onLongPress, | |
), | |
) | |
.toList()), | |
), | |
), | |
Positioned( | |
bottom: 20.0, | |
right: 10.0, | |
left: 10.0, | |
child: NativeButton( | |
child: widget.buttonText, | |
buttonColor: Colors.blue, | |
onPressed: widget.onPressed, | |
)), | |
], | |
), | |
))); | |
} | |
} | |
// Native Button | |
class NativeButton extends StatelessWidget { | |
final Widget child; | |
final VoidCallback onPressed; | |
final Color buttonColor; | |
final EdgeInsetsGeometry padding; | |
NativeButton({ | |
this.child, | |
this.onPressed, | |
this.padding, | |
this.buttonColor, | |
}); | |
@override | |
Widget build(BuildContext context) { | |
return (Padding( | |
padding: padding == null ? EdgeInsets.all(0.0) : padding, | |
child: Platform.isIOS | |
? CupertinoButton( | |
padding: padding, | |
color: buttonColor, | |
child: child, | |
onPressed: onPressed, | |
) | |
: FlatButton( | |
color: buttonColor, | |
padding: padding, | |
child: child, | |
onPressed: onPressed, | |
), | |
)); | |
} | |
} | |
// Native Dialog Action for Native Dialog | |
class NativeDialogAction { | |
final String text; | |
final bool isDestructive; | |
final VoidCallback onPressed; | |
NativeDialogAction( | |
{@required this.text, this.isDestructive, @required this.onPressed}); | |
} | |
// Native Dialog | |
class NativeDialog extends StatefulWidget { | |
final String title; | |
final String content; | |
final TextStyle textStyle; | |
final List<NativeDialogAction> actions; | |
NativeDialog( | |
{@required this.actions, | |
this.title, | |
@required this.content, | |
this.textStyle}); | |
@override | |
_NativeDialogState createState() => _NativeDialogState(); | |
} | |
class _NativeDialogState extends State<NativeDialog> { | |
@override | |
Widget build(BuildContext context) { | |
return (Platform.isIOS | |
? CupertinoAlertDialog( | |
title: widget.title == null | |
? null | |
: Text( | |
widget.title, | |
style: widget.textStyle, | |
), | |
content: Text( | |
widget.content, | |
style: widget.textStyle, | |
), | |
actions: widget.actions | |
.map((NativeDialogAction item) => CupertinoDialogAction( | |
child: Text(item.text), | |
isDestructiveAction: item.isDestructive, | |
onPressed: item.onPressed)) | |
.toList()) | |
: AlertDialog( | |
title: widget.title == null | |
? null | |
: Text( | |
widget.title, | |
style: widget.textStyle, | |
), | |
content: Text( | |
widget.content, | |
style: widget.textStyle, | |
), | |
actions: widget.actions | |
.map((NativeDialogAction item) => FlatButton( | |
child: Text( | |
item.text, | |
style: TextStyle( | |
color: | |
item.isDestructive ? Colors.redAccent : null), | |
), | |
onPressed: item.onPressed, | |
)) | |
.toList())); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment