Created
August 9, 2018 10:03
-
-
Save long1eu/0cac0f67eeb3115941cb0366929cc946 to your computer and use it in GitHub Desktop.
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 'dart:async'; | |
import 'package:flutter/material.dart'; | |
void main() => runApp(new MyApp()); | |
class MyApp extends StatefulWidget { | |
static MyAppState of(BuildContext context) => (context.inheritFromWidgetOfExactType(AppState) as AppState).data; | |
@override | |
MyAppState createState() => new MyAppState(); | |
} | |
class MyAppState extends State<MyApp> { | |
final GlobalKey<NavigatorState> key = GlobalKey<NavigatorState>(); | |
bool isLocked = true; | |
NavigatorState get navigator => key.currentState; | |
void pushRoute(FakeRoute route) { | |
navigator.pushReplacement(PageRouteBuilder<void>( | |
pageBuilder: (BuildContext _, Animation __, Animation ___) => appRoutes[route](), | |
)); | |
} | |
void setIsLocked(bool isLocked) { | |
if (this.isLocked != isLocked) { | |
setState(() => this.isLocked = isLocked); | |
} | |
} | |
@override | |
Widget build(BuildContext context) { | |
return AppState( | |
data: this, | |
isLocked: isLocked, | |
child: new MaterialApp( | |
navigatorKey: key, | |
title: 'Flutter Demo', | |
theme: new ThemeData( | |
primarySwatch: Colors.blue, | |
), | |
home: const SplashScreen(), | |
), | |
); | |
} | |
} | |
class AppState extends InheritedWidget { | |
const AppState({this.data, this.isLocked, Widget child}) : super(child: child); | |
final MyAppState data; | |
final bool isLocked; | |
@override | |
bool updateShouldNotify(InheritedWidget oldWidget) => (oldWidget as AppState).isLocked != isLocked; | |
} | |
class SplashScreen extends StatefulWidget { | |
const SplashScreen(); | |
@override | |
SplashScreenState createState() => new SplashScreenState(); | |
} | |
class SplashScreenState extends State<SplashScreen> { | |
@override | |
void initState() { | |
super.initState(); | |
Future.delayed(const Duration(seconds: 3), () { | |
MyApp.of(context).pushRoute(FakeRoute.public); | |
}); | |
} | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
body: Center( | |
child: Column( | |
mainAxisAlignment: MainAxisAlignment.spaceAround, | |
children: <Widget>[ | |
FlutterLogo(size: 240.0), | |
CircularProgressIndicator(strokeWidth: 1.0), | |
], | |
), | |
), | |
); | |
} | |
} | |
Map<FakeRoute, Widget Function()> appRoutes = <FakeRoute, Widget Function()>{ | |
PublicNavigator.route: () => const PublicNavigator(), | |
PrivateNavigator.route: () => const PrivateNavigator(), | |
}; | |
Route<dynamic> onGenerateRoute(RouteSettings settings, Map<String, WidgetBuilder> routes) { | |
final String name = settings.name; | |
final WidgetBuilder builder = routes[name]; | |
return MaterialPageRoute<dynamic>( | |
builder: builder, | |
settings: settings, | |
); | |
} | |
enum FakeRoute { public, private } | |
class PublicRoutes { | |
static const String public1 = '/'; | |
static const String public2 = '/2'; | |
} | |
class PublicNavigator extends StatelessWidget { | |
static const FakeRoute route = FakeRoute.public; | |
const PublicNavigator(); | |
@override | |
Widget build(BuildContext context) { | |
final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{ | |
PublicRoutes.public1: (BuildContext context) => const PublicPage(i: 1), | |
PublicRoutes.public2: (BuildContext context) => const PublicPage(i: 2), | |
}; | |
return Navigator( | |
key: key, | |
initialRoute: PublicRoutes.public1, | |
onGenerateRoute: (RouteSettings settings) => onGenerateRoute(settings, routes), | |
); | |
} | |
} | |
class PublicPage extends StatelessWidget { | |
const PublicPage({Key key, @required this.i}) : super(key: key); | |
final int i; | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar(title: Text('Public page $i')), | |
body: Center( | |
child: new Text( | |
'Public page $i', | |
style: Theme.of(context).textTheme.body1, | |
), | |
), | |
floatingActionButton: RaisedButton.icon( | |
color: Theme.of(context).primaryColor, | |
icon: Icon( | |
Icons.navigate_next, | |
color: Colors.white, | |
), | |
label: Text( | |
i == 1 ? '2' : 'Private', | |
style: const TextStyle( | |
color: Colors.white, | |
), | |
), | |
onPressed: i == 1 | |
? () => Navigator.of(context).pushNamed(PublicRoutes.public2) | |
: () => MyApp.of(context).pushRoute(FakeRoute.private), | |
), | |
); | |
} | |
} | |
class PrivateRoutes { | |
static const String private1 = '/'; | |
static const String private2 = '/2'; | |
static const String locked = '/locked'; | |
} | |
class PrivateNavigator extends StatelessWidget { | |
static const FakeRoute route = FakeRoute.private; | |
const PrivateNavigator(); | |
@override | |
Widget build(BuildContext context) { | |
final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{ | |
PrivateRoutes.private1: (BuildContext context) => const PrivatePage(i: 1), | |
PrivateRoutes.private2: (BuildContext context) => const PrivatePage(i: 2), | |
PrivateRoutes.locked: (BuildContext context) => const LockPage(), | |
}; | |
return Stack( | |
children: <Widget>[ | |
Navigator( | |
key: key, | |
initialRoute: PrivateRoutes.private1, | |
onGenerateRoute: (RouteSettings settings) => onGenerateRoute(settings, routes), | |
), | |
MyApp.of(context).isLocked ? const LockPage() : Container(), | |
], | |
); | |
} | |
} | |
class PrivatePage extends StatelessWidget { | |
const PrivatePage({Key key, @required this.i}) : super(key: key); | |
final int i; | |
@override | |
Widget build(BuildContext context) { | |
return Theme( | |
data: Theme.of(context).copyWith( | |
primaryColor: Colors.red, | |
accentColor: Colors.grey, | |
), | |
child: Builder( | |
builder: (BuildContext context) { | |
return Scaffold( | |
appBar: AppBar(title: Text('Private page $i')), | |
body: Center( | |
child: new Text( | |
'Private page $i', | |
style: Theme.of(context).textTheme.body1, | |
), | |
), | |
floatingActionButton: Container( | |
height: 120.0, | |
child: i == 1 | |
? Column( | |
mainAxisAlignment: MainAxisAlignment.spaceBetween, | |
children: <Widget>[ | |
FloatingActionButton( | |
child: Icon(Icons.lock), | |
onPressed: () { | |
MyApp.of(context).setIsLocked(true); | |
}, | |
), | |
RaisedButton.icon( | |
color: Colors.grey, | |
icon: Icon( | |
Icons.navigate_next, | |
color: Colors.white, | |
), | |
label: Text( | |
'2', | |
style: const TextStyle( | |
color: Colors.white, | |
), | |
), | |
onPressed: () => Navigator.of(context).pushNamed(PrivateRoutes.private2), | |
), | |
], | |
) | |
: FloatingActionButton( | |
child: Icon(Icons.lock), | |
onPressed: () { | |
MyApp.of(context).setIsLocked(true); | |
}, | |
), | |
), | |
); | |
}, | |
), | |
); | |
} | |
} | |
class LockPage extends StatelessWidget { | |
const LockPage(); | |
@override | |
Widget build(BuildContext context) { | |
return Theme( | |
data: Theme.of(context).copyWith( | |
primaryColor: Colors.purple, | |
accentColor: Colors.deepPurple, | |
), | |
child: Builder( | |
builder: (BuildContext context) { | |
return Scaffold( | |
backgroundColor: Theme.of(context).primaryColor, | |
body: Padding( | |
padding: const EdgeInsets.all(16.0), | |
child: Column( | |
mainAxisAlignment: MainAxisAlignment.spaceEvenly, | |
children: <Widget>[ | |
Text('Enter 5 characters to unlock, if you can, the keyboard won\'t open.'), | |
TextField( | |
decoration: InputDecoration( | |
hintText: 'password', | |
), | |
onChanged: (String text) { | |
if (text.length >= 5) { | |
MyApp.of(context).setIsLocked(false); | |
} | |
}, | |
), | |
Text('Or you can cheat by taping the FloatingActionButton.'), | |
], | |
), | |
), | |
floatingActionButton: FloatingActionButton( | |
child: Icon(Icons.lock_open), | |
onPressed: () => MyApp.of(context).setIsLocked(false), | |
), | |
); | |
}, | |
), | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment