Last active
July 5, 2018 12:38
-
-
Save rodydavis/d002038e09718d179637afc46de5c6aa 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 { | |
// Example to Put on Login Function to Only Show on Version Change | |
// var prefs = await SharedPreferences.getInstance(); | |
// String _lastVersion = prefs.getString('lastVersion'); | |
// _lastVersion == null ? _lastVersion = "" : _lastVersion = _lastVersion; | |
// String _projectVersion = await GetVersion.projectVersion; | |
// if (!_lastVersion.contains(_projectVersion)) { | |
// prefs.setString('lastVersion', _projectVersion); | |
// Navigator.of(context).pushNamed("/start_page"); | |
// } else { | |
// Navigator.of(context).pushNamed("/menu"); | |
// } | |
// 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) { | |
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', | |
style: TextStyle( | |
color: Colors.white, | |
), | |
), | |
// Create a List of WhatsNewItem for use in the Whats New Page | |
// Create as many as you need, it will be scrollable | |
items: <ListTile>[ | |
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('View and edit the current thumbnail'), | |
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."); | |
}, | |
), | |
ListTile( | |
title: Text('Video Upload Workflow'), | |
subtitle: Text( | |
'New clean look and eaiser workflow for uploading videos captured on the camera or selected from the gallery'), | |
leading: Icon(Icons.file_upload), | |
onTap: () { | |
Navigator.of(context).pushNamed("/camera"); | |
}, | |
), | |
], //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) => item).toList()), | |
), | |
), | |
Positioned( | |
bottom: 5.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