Snippets

Kevin Armstrong Navigate Anywhere

Created by Kevin Armstrong last modified
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

import 'settings.dart';
import 'state.dart';

void main() {
  List<Color> colors = Colors.primaries.sublist(0);
  colors.shuffle();

  runApp(SettingsContainer(
    child: MaterialApp(
      home: MyApp(),
    ),
    settings: Settings(
      accentColor: colors.first,
    ),
  ));
}

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(),
        ),
      ),
    );
  }
}
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) {
        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,
        );
      },
    );
  }
}

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,
      ),
    );
  }
}
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,
    );
  }
}

Comments (0)