Snippets

Kevin Armstrong Navigate Anywhere

Updated by Kevin Armstrong

File settings.dart Modified

  • Ignore whitespace
  • Hide word diff
       key: settingsNavKey,
       initialRoute: 'settings/home',
       onGenerateRoute: (routeSettings) {
-        bool fullScreen = false;
         WidgetBuilder builder;
         switch (routeSettings.name) {
           case 'settings/home':
         return MaterialPageRoute(
           builder: builder,
           settings: routeSettings,
-          fullscreenDialog: fullScreen,
         );
       },
     );
Updated by Kevin Armstrong

File main.dart Modified

  • Ignore whitespace
  • Hide word diff
 import 'state.dart';
 
 void main() {
+  List<Color> colors = Colors.primaries.sublist(0);
+  colors.shuffle();
+
   runApp(SettingsContainer(
     child: MaterialApp(
       home: MyApp(),
     ),
-    settings: Settings(accentColor: Colors.green),
+    settings: Settings(
+      accentColor: colors.first,
+    ),
   ));
 }
 
Created by Kevin Armstrong

File main.dart Added

  • Ignore whitespace
  • Hide word diff
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+
+import 'settings.dart';
+import 'state.dart';
+
+void main() {
+  runApp(SettingsContainer(
+    child: MaterialApp(
+      home: MyApp(),
+    ),
+    settings: Settings(accentColor: Colors.green),
+  ));
+}
+
+class MyApp extends StatelessWidget {
+  @override
+  Widget build(BuildContext context) {
+    final settings = SettingsContainer.of(context).settings;
+    return Theme(
+      data: settings.isDark
+          ? ThemeData.dark()
+          : ThemeData.light().copyWith(
+              primaryTextTheme: TextTheme(
+                title: TextStyle(
+                  color: Colors.grey.shade800,
+                ),
+              ),
+              appBarTheme: AppBarTheme(
+                brightness:
+                    settings.isDark ? Brightness.dark : Brightness.light,
+                color: Colors.grey.shade100,
+              ),
+            ),
+      child: Scaffold(
+        appBar: AppBar(
+          title: Text('Navigate Anywhere'),
+          elevation: 0.0,
+        ),
+        body: Center(
+          child: _makeButton(context),
+        ),
+      ),
+    );
+  }
+
+  Widget _makeButton(context) {
+    final container = SettingsContainer.of(context);
+    bool isAndroid = Theme.of(context).platform == TargetPlatform.android;
+    var showDialogAction = () {
+      showDialog(
+        context: context,
+        builder: (context) {
+          return _makeDialog(isAndroid);
+        },
+      );
+    };
+    var buttonChild = Text(
+      'Show Settings',
+      style: TextStyle(
+        color: container.settings.textColor,
+      ),
+    );
+    if (isAndroid) {
+      return FlatButton(
+        onPressed: showDialogAction,
+        color: container.settings.accentColor,
+        child: buttonChild,
+      );
+    } else {
+      return CupertinoButton(
+        onPressed: showDialogAction,
+        color: container.settings.accentColor,
+        child: buttonChild,
+      );
+    }
+  }
+
+  Dialog _makeDialog(bool isAndroid) {
+    double _cornerRadius = isAndroid ? 0 : 12;
+    return Dialog(
+      shape: RoundedRectangleBorder(
+          borderRadius: BorderRadius.circular(_cornerRadius)), //this right here
+      child: ClipRRect(
+        borderRadius: BorderRadius.circular(_cornerRadius),
+        child: Container(
+          height: 300.0,
+          width: 350.0,
+          child: SettingsDialog(),
+        ),
+      ),
+    );
+  }
+}

File settings.dart Added

  • Ignore whitespace
  • Hide word diff
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+
+import 'state.dart';
+
+class SettingsDialog extends StatelessWidget {
+  final GlobalKey<NavigatorState> settingsNavKey = GlobalKey<NavigatorState>();
+
+  SettingsDialog();
+
+  @override
+  Widget build(BuildContext context) {
+    return Navigator(
+      key: settingsNavKey,
+      initialRoute: 'settings/home',
+      onGenerateRoute: (routeSettings) {
+        bool fullScreen = false;
+        WidgetBuilder builder;
+        switch (routeSettings.name) {
+          case 'settings/home':
+            builder = (BuildContext _) => SettingsHome(context);
+            break;
+          case 'settings/color':
+            builder = (BuildContext _) => SettingsAccentColor(context);
+            break;
+        }
+        return MaterialPageRoute(
+          builder: builder,
+          settings: routeSettings,
+          fullscreenDialog: fullScreen,
+        );
+      },
+    );
+  }
+}
+
+class SettingsHome extends StatelessWidget {
+  final BuildContext topContext;
+
+  SettingsHome(this.topContext);
+
+  @override
+  Widget build(BuildContext context) {
+    final container = SettingsContainer.of(topContext);
+    bool isAndroid = Theme.of(context).platform == TargetPlatform.android;
+    bool isDark = container.settings.isDark;
+    Color accentColor = container.settings.accentColor;
+    return new Scaffold(
+      appBar: new AppBar(
+        title: Text('Settings'),
+        elevation: 0.0,
+        actions: <Widget>[
+          IconButton(
+            onPressed: () => Navigator.of(topContext).pop(),
+            icon: Icon(Icons.close),
+          ),
+        ],
+      ),
+      body: ListView(
+        children: <Widget>[
+          ListTile(
+            title: Text('Dark Mode'),
+            trailing: Switch.adaptive(
+              value: isDark,
+              onChanged: (bool value) {
+                container.updateSettings(isDark: value);
+              },
+              activeColor: container.settings.accentColor,
+            ),
+          ),
+          ListTile(
+            title: Text('Accent Color'),
+            trailing: SizedBox(
+              width: 100,
+              child: Row(
+                mainAxisAlignment: MainAxisAlignment.end,
+                children: <Widget>[
+                  Container(
+                    width: 30,
+                    height: 30,
+                    decoration: BoxDecoration(
+                      color: accentColor,
+                      shape: BoxShape.circle,
+                    ),
+                  ),
+                  Icon(Icons.chevron_right),
+                ],
+              ),
+            ),
+            onTap: () => Navigator.pushNamed(context, 'settings/color'),
+          ),
+          ListTile(
+            title: Text('FAQs'),
+            trailing: Icon(Icons.info_outline),
+            onTap: () {
+              showDialog(
+                  context: topContext,
+                  builder: (BuildContext _) {
+                    String title = 'Open External';
+                    String content =
+                        'Are you sure you want to navigate outside of app?';
+                    return isAndroid
+                        ? AlertDialog(
+                            title: Text(title),
+                            content: Text(content),
+                            actions: <Widget>[
+                              FlatButton(
+                                child: Text('No'),
+                                onPressed: () => Navigator.pop(topContext),
+                              ),
+                              FlatButton(
+                                child: Text('Yes'),
+                                onPressed: () => Navigator.pop(topContext),
+                              ),
+                            ],
+                          )
+                        : CupertinoAlertDialog(
+                            title: Text(title),
+                            content: Text(content),
+                            actions: <Widget>[
+                              CupertinoDialogAction(
+                                child: Text('No'),
+                                isDestructiveAction: true,
+                                onPressed: () => Navigator.pop(topContext),
+                              ),
+                              CupertinoDialogAction(
+                                child: Text('Yes'),
+                                isDefaultAction: true,
+                                onPressed: () => Navigator.pop(topContext),
+                              ),
+                            ],
+                          );
+                  });
+            },
+          ),
+        ],
+      ),
+    );
+  }
+}
+
+class SettingsAccentColor extends StatelessWidget {
+  final BuildContext topContext;
+
+  SettingsAccentColor(this.topContext);
+
+  @override
+  Widget build(BuildContext context) {
+    final container = SettingsContainer.of(topContext);
+    Color accentColor = container.settings.accentColor;
+    Color iconColor = container.settings.textColor;
+    return new Scaffold(
+      appBar: new AppBar(
+        title: Text('Select Accent Color'),
+        elevation: 0.0,
+      ),
+      body: ListView.builder(
+        itemBuilder: (context, index) {
+          return Container(
+            child: ListTile(
+              trailing: accentColor == Colors.primaries[index]
+                  ? Icon(
+                      Icons.radio_button_checked,
+                      color: iconColor,
+                    )
+                  : Container(),
+              onTap: () {
+                container.updateSettings(color: Colors.primaries[index]);
+                Navigator.pop(context, Colors.primaries[index]);
+              },
+            ),
+            color: Colors.primaries[index],
+            margin: EdgeInsets.all(5.0),
+          );
+        },
+        itemCount: Colors.primaries.length,
+      ),
+    );
+  }
+}

File state.dart Added

  • Ignore whitespace
  • Hide word diff
+import 'package:flutter/material.dart';
+
+class Settings {
+  final bool isDark;
+  final Color accentColor;
+
+  Settings({this.isDark: false, this.accentColor});
+
+  Settings copyWith({bool isDark, Color accentColor}) {
+    return Settings(
+      isDark: isDark ?? this.isDark,
+      accentColor: accentColor ?? this.accentColor,
+    );
+  }
+
+  Color get textColor {
+    if (accentColor.computeLuminance() > 0.6) {
+      return Colors.black;
+    } else {
+      return Colors.white;
+    }
+  }
+}
+
+class InheritedSettingsContainer extends InheritedWidget {
+  final SettingsContainerState data;
+
+  InheritedSettingsContainer({
+    Key key,
+    @required this.data,
+    @required Widget child,
+  }) : super(key: key, child: child);
+
+  @override
+  bool updateShouldNotify(InheritedSettingsContainer old) => true;
+}
+
+class SettingsContainer extends StatefulWidget {
+  final Widget child;
+  final Settings settings;
+
+  SettingsContainer({
+    @required this.child,
+    this.settings,
+  });
+
+  static SettingsContainerState of(BuildContext context) {
+    return (context.inheritFromWidgetOfExactType(InheritedSettingsContainer)
+            as InheritedSettingsContainer)
+        .data;
+  }
+
+  @override
+  SettingsContainerState createState() => new SettingsContainerState();
+}
+
+class SettingsContainerState extends State<SettingsContainer> {
+  Settings settings;
+
+  @override
+  void initState() {
+    settings = widget.settings ?? new Settings();
+    super.initState();
+  }
+
+  void updateSettings({isDark, color}) {
+    setState(() {
+      settings = settings.copyWith(
+        isDark: isDark,
+        accentColor: color,
+      );
+    });
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return new InheritedSettingsContainer(
+      data: this,
+      child: widget.child,
+    );
+  }
+}
HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.