Flurry Drawer In Flutter

Flurry Drawer In Flutter :

Screenshot :

Flurry Drawer In Flutter

main.dart

import 'package:flutter/material.dart';
import 'package:flurry_navigation/flurry_navigation.dart';
import 'package:flurry_navigation/flurry_menu.dart';
import 'home_page.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  //Decalre active screen var with the the default screen somewhere accesible to the contentScreen attributes
  var activeScreen = homepage;
  Widget build(BuildContext context) {
    return new FlurryNavigation(
      // The Icon data of the icon the BottomLeft
      expandIcon: Icon(Icons.menu, size: 25),
      // The size of the icon on the BottomLeft
      iconSize: 50.0,
      // The content of the screen
      contentScreen: activeScreen,
      menuScreen: new MenuScreen(
        bgColor: Color.fromRGBO(121, 134, 203, 1),
        menu: new Menu(
          items: [
            new MenuItem(
                id:
                    'hom', //You can set this to whatever you want but dont duplicate it
                icon:
                    'assets/hom.png', //Set this to the data for the icon of the button
                isSelected: true,
                selectedBtnColor: Color.fromRGBO(38, 198, 218, 1),
                btnShape: BoxShape.rectangle),
            new MenuItem(
                id: 'sta',
                icon: 'assets/sta.png',
                isSelected: false,
                selectedBtnColor: Color.fromRGBO(38, 198, 218, 1),
                btnShape: BoxShape.rectangle),
            new MenuItem(
              id: 'doc',
              icon: 'assets/doc.png',
              isSelected: false,
              selectedBtnColor: Color.fromRGBO(38, 198, 218, 1),
            ),
            new MenuItem(
              id: 'set',
              icon: 'assets/set.png',
              isSelected: false,
              selectedBtnColor: Color.fromRGBO(38, 198, 218, 1),
            ),
          ],
        ),
        onMenuItemSelected: (String itemId) {
          if (itemId == 'hom') {
            setState(() => activeScreen = homepage);
          } else if (itemId == 'sta') {
            setState(() => activeScreen = homepage);
          } else if (itemId == 'doc') {
            setState(() => activeScreen = homepage);
          } else if (itemId == 'loc') {
            setState(() => activeScreen = homepage);
          } else if (itemId == 'set') {
            setState(() => activeScreen = homepage);
          }
        },
      ),
    );
  }
}

flurry_menu.dart

import 'package:flutter/material.dart';
import 'flurry_navigation.dart';

final menuScreenKey = new GlobalKey(debugLabel: 'MenuScreen');

class MenuScreen extends StatefulWidget {
  final Menu menu;
  final Function(String) onMenuItemSelected;
  final Color bgColor;
  MenuScreen({
    this.menu,
    this.onMenuItemSelected,
    this.bgColor,
  }) : super(key: menuScreenKey);
  @override
  createState() {
    return new CustomRadioState();
  }
}

class CustomRadioState extends State<MenuScreen> {
  List<RadioModel> sampleData = new List<RadioModel>();

  @override
  void initState() {
    super.initState();
    for (var i = 0; i < widget.menu.items.length; ++i) {
      sampleData.add(new RadioModel(
        widget.menu.items[i].isSelected,
        widget.menu.items[i].icon,
        widget.menu.items[i].id,
        widget.menu.items[i].selectedBtnColor,
        widget.menu.items[i].disabledBtnColor,
        widget.menu.items[i].selectedShadowColor,
        widget.menu.items[i].disabledShadowColor,
        widget.menu.items[i].btnShape,
      ));
    }
  }

  @override
  Widget build(BuildContext context) {
    return new FlurryNavigationMenuController(
        builder: (BuildContext context, MenuController menuController) {
      return new Scaffold(
        backgroundColor: widget.bgColor,
        body: FractionallySizedBox(
          heightFactor: 0.69,
          widthFactor: 0.3,
          child: ListView.builder(
            itemCount: sampleData.length,
            itemBuilder: (BuildContext context, int index) {
              return new InkWell(
                splashColor: Colors.transparent,
                onTap: () {
                  widget.onMenuItemSelected(sampleData[index].id);
                  setState(() {
                    sampleData.forEach((element) => element.isSelected = false);
                    sampleData[index].isSelected = true;
                  });
                  menuController.close();
                },
                child: new RadioItem(sampleData[index]),
              );
            },
          ),
        ),
      );
    });
  }
}

class RadioItem extends StatelessWidget {
  final RadioModel _item;
  RadioItem(this._item);
  @override
  Widget build(BuildContext context) {
    return new Container(
      margin: new EdgeInsets.all(15.0),
      child: new Center(
        child: new Container(
          alignment: Alignment.center,
          height: 60.0,
          width: 60.0,
          child: FractionallySizedBox(
            heightFactor: 0.7,
            widthFactor: 0.7,
            child: Icon(Icons.home),
            /*IconButton(
              icon: Image.asset(_item.icon),
            ),*/
          ),
          decoration: new BoxDecoration(
            color: _item.isSelected
                ? _item.selectedBtnColor
                : _item.disabledBtnColor,
            border: new Border.all(width: 1.0, color: Colors.transparent),
            shape: _item.btnShape,
            boxShadow: <BoxShadow>[
              BoxShadow(
                  color: _item.isSelected
                      ? _item.selectedShadowColor
                      : _item.disabledShadowColor,
                  offset: Offset(0, 5.0),
                  blurRadius: 5.0,
                  spreadRadius: 1),
            ],
          ),
        ),
      ),
    );
  }
}

class MenuItem {
  final bool isSelected;
  final String icon;
  final String id;
  final Color selectedBtnColor;
  Color disabledBtnColor;
  Color selectedShadowColor;
  Color disabledShadowColor;
  BoxShape btnShape;

  MenuItem(
      {this.icon,
      this.id,
      this.isSelected,
      this.selectedBtnColor,
      this.disabledBtnColor = Colors.transparent,
      this.selectedShadowColor = Colors.blueGrey,
      this.disabledShadowColor = Colors.transparent,
      this.btnShape = BoxShape.circle});
}

class RadioModel {
  bool isSelected;
  final String icon;
  final String id;
  final Color selectedBtnColor;
  final Color disabledBtnColor;
  final Color selectedShadowColor;
  final Color disabledShadowColor;
  final BoxShape btnShape;
  RadioModel(
      this.isSelected,
      this.icon,
      this.id,
      this.selectedBtnColor,
      this.disabledBtnColor,
      this.selectedShadowColor,
      this.disabledShadowColor,
      this.btnShape);
}

class Menu {
  final List<MenuItem> items;

  Menu({
    this.items,
  });
}

flurry_navigation.dart

import 'package:flutter/material.dart';
class FlurryNavigation extends StatefulWidget {
  final Widget menuScreen;
  final Screen contentScreen;
  final Icon expandIcon;
  final double iconSize;

  FlurryNavigation(
      {this.menuScreen, this.contentScreen, this.expandIcon, this.iconSize});

  @override
  _FlurryNavigationState createState() => new _FlurryNavigationState();
}

class _FlurryNavigationState extends State<FlurryNavigation>
    with TickerProviderStateMixin {
  MenuController menuController;
  Curve scaleDownCurve = new Interval(0.0, 1.0, curve: Curves.linear);
  Curve scaleUpCurve = new Interval(0.0, 1.0, curve: Curves.linear);
  Curve slideOutCurve = new Interval(0.0, 1.0, curve: Curves.elasticOut);
  Curve slideInCurve = new Interval(0.0, 1.0, curve: Curves.ease);

  @override
  void initState() {
    super.initState();

    menuController = new MenuController(
      vsync: this,
    )..addListener(() => setState(() {}));
  }

  @override
  void dispose() {
    menuController.dispose();
    super.dispose();
  }

  createContentDisplay() {
    return zoomAndSlideContent(
      new Container(
        child: new Scaffold(
            body: Column(children: <Widget>[
          Expanded(
            child: widget.contentScreen.contentBuilder(context),
          ),
          Row(
            children: <Widget>[
              IconButton(
                icon: widget.expandIcon,
                onPressed: () {
                  menuController.toggle();
                },
                alignment: Alignment.bottomLeft,
                padding: EdgeInsets.all(0),
                iconSize: widget.iconSize,
              )
            ],
          ),
        ])),
      ),
    );
  }

  zoomAndSlideContent(Widget content) {
    //slidePercent is not used right now but it may be used in future versions
    var /*slidePercent, */scalePercent;
    switch (menuController.state) {
      case MenuState.closed:
        //slidePercent = 0.0;
        scalePercent = 0.0;
        break;
      case MenuState.open:
        //slidePercent = 1.0;
        scalePercent = 1.0;
        break;
      case MenuState.opening:
        //slidePercent = slideOutCurve.transform(menuController.percentOpen);
        scalePercent = scaleDownCurve.transform(menuController.percentOpen);
        break;
      case MenuState.closing:
        //slidePercent = slideInCurve.transform(menuController.percentOpen);
        scalePercent = scaleUpCurve.transform(menuController.percentOpen);
        break;
    }
    var contentScale;
    double cornerRadius = 0;
    return OrientationBuilder(builder: (context, orientation) {
      contentScale = 1.0 - (0.3 * scalePercent);
      cornerRadius = 260 * menuController.percentOpen;

      return new Transform(
        transform: new Matrix4.translationValues(0.0, 0.0, 0.0)
          ..scale(contentScale, contentScale),
        alignment: orientation == Orientation.portrait
            ? Alignment.topRight
            : Alignment.topRight,
        child: new ClipRRect(
            borderRadius: new BorderRadius.only(
                bottomLeft: Radius.circular(cornerRadius)),
            child: content),
      );
    });
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        widget.menuScreen,
        createContentDisplay(),
      ],
    );
  }
}

class FlurryNavigationMenuController extends StatefulWidget {
  final FlurryNavigationBuilder builder;

  FlurryNavigationMenuController({
    this.builder,
  });

  @override
  FlurryNavigationMenuControllerState createState() {
    return new FlurryNavigationMenuControllerState();
  }
}

class FlurryNavigationMenuControllerState
    extends State<FlurryNavigationMenuController> {
  MenuController menuController;

  @override
  void initState() {
    super.initState();

    menuController = getMenuController(context);
    menuController.addListener(_onMenuControllerChange);
  }

  @override
  void dispose() {
    menuController.removeListener(_onMenuControllerChange);
    super.dispose();
  }

  getMenuController(BuildContext context) {
    final navigationState =
        context.ancestorStateOfType(new TypeMatcher<_FlurryNavigationState>())
            as _FlurryNavigationState;
    return navigationState.menuController;
  }

  _onMenuControllerChange() {
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return widget.builder(context, getMenuController(context));
  }
}

typedef Widget FlurryNavigationBuilder(
    BuildContext context, MenuController menuController);

class Screen {
  final WidgetBuilder contentBuilder;

  Screen({
    this.contentBuilder,
  });
}

class MenuController extends ChangeNotifier {
  final TickerProvider vsync;
  final AnimationController _animationController;
  MenuState state = MenuState.closed;

  MenuController({
    this.vsync,
  }) : _animationController = new AnimationController(vsync: vsync) {
    _animationController
      ..duration = const Duration(milliseconds: 300)
      ..addListener(() {
        notifyListeners();
      })
      ..addStatusListener((AnimationStatus status) {
        switch (status) {
          case AnimationStatus.forward:
            state = MenuState.opening;
            break;
          case AnimationStatus.reverse:
            state = MenuState.closing;
            break;
          case AnimationStatus.completed:
            state = MenuState.open;
            break;
          case AnimationStatus.dismissed:
            state = MenuState.closed;
            break;
        }
        notifyListeners();
      });
  }

  @override
  dispose() {
    _animationController.dispose();
    super.dispose();
  }

  get percentOpen {
    return _animationController.value;
  }

  open() {
    _animationController.forward();
  }

  close() {
    _animationController.reverse();
  }

  toggle() {
    if (state == MenuState.open) {
      close();
    } else if (state == MenuState.closed) {
      open();
    }
  }
}

enum MenuState {
  closed,
  opening,
  open,
  closing,
}

home_page.dart

import 'package:flutter/material.dart';
import 'package:flurry_navigation/flurry_navigation.dart';

final homepage = new Screen(
    contentBuilder: (BuildContext context) {
      return new Center(
        child: new Container(
          height:100.0,
          child: new Padding(
            padding: const EdgeInsets.all(25.0),
            child: new Column(
              children: [
                new Expanded(
                    child: new Center(
                        child: new Text('Flutter Tutorial')
                    )
                )
              ],
            ),
          ),
        ),

      );
    }
);

The flutter tutorial  is a website that bring you the latest and amazing resources of code. All the languages codes are included in this website. The languages like flutter, android, java,kotlin etc.with the help of this languages any user can develop the beautiful application

For more information about Flutter. visit www.fluttertutorial.in