Skip to content

Instantly share code, notes, and snippets.

@rodydavis
Last active July 5, 2018 12:38
Show Gist options
  • Save rodydavis/d002038e09718d179637afc46de5c6aa to your computer and use it in GitHub Desktop.
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)
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