Flutter device dependant layout with one class?

Viewed 141

I am trying to do a layout like this:

The layout I am trying to do

The layout class I am trying to do is as follows:

class Layout extends StatefulWidget {
  @required
  final String title;
  @required
  final Widget leftView;
  @required
  final Widget rightView;

  const Layout({Key key, this.title, this.leftView, this.rightView})
      : super(key: key);

  @override
  _LayoutState createState() => _LayoutState();
}

class _LayoutState extends State<Layout> {
  String title;
  Widget leftView;
  Widget rightView;

  @override
  Widget build(BuildContext context) {
    var screenSize = MediaQuery.of(context).size;
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      drawer: (screenSize.width < Constants.MOBILE_WIDTH_SIZE
          ? DrawerPage()
          : null),
      //TODO: Need to be able to change based on some global variable as comments section can't have something else down there
      floatingActionButtonLocation:
          screenSize.width < Constants.DESKTOP_WIDTH_SIZE
              ? FloatingActionButtonLocation.miniEndFloat
              : FloatingActionButtonLocation.miniCenterFloat,
      body: getRelevantLayout(screenSize.width, screenSize.height),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          // Add your onPressed code here!
        },
        child: const Icon(Icons.add),
        //backgroundColor: Colors.orangeAccent,
      ),
    );
  }

  Widget getRelevantLayout(double _width, double _height) {
    if (_width < Constants.MOBILE_WIDTH_SIZE) {
      // mobile Layout
      return leftView;
    } else if (_width < Constants.DESKTOP_WIDTH_SIZE) {
      // tablet layout
      return Row(
        children: [
          DrawerPage(),
          Expanded(
            child: leftView,
          ),
        ],
      );
    } else {
      // desktop layout
      return Row(
        children: [
          DrawerPage(),
          Flexible(flex: 9, child: leftView),
          Flexible(flex: 10, child: rightView),
        ],
      );
    }
  }

  @override
  void initState() {
    title = widget.title;
    leftView = widget.leftView;
    rightView = widget.rightView;
    super.initState();
  }
}

The idea I was trying to do is in my original routes set up my views i.e

      routes: {
        '/': (context) => Layout(
              title: '$_title - Home',
              leftView: ListSectionView(),
              rightView: WhatsNewView(),
            ),

Then my idea was to in say the leftview, to set up the rightView, although clearly unless leftview is set up again, it won't work. Only when it is in tablet or phone view do I wish to do the usual Navigation.push

I have tried my best to find a solution like this but to no avail. So any suggestion on how this could be achieved would be greatly appreciated.

1 Answers

I like to make the whole widget tree for each orientation in a separated widget and choose which one to use based on screen width and orientation. I use constants for the sizes of the screen and functions when i want to resize only a few components. Ex:

const double smallScreenWidth = 360.0;
const double mediumScreenWidth = 412.0;
const double bigScreenWidth = 480.0;

double iconSize(BuildContext context) {
  double screenWidth = 1;

  if (MediaQuery.of(context).orientation == Orientation.portrait)
    screenWidth = MediaQuery.of(context).size.width;
  else
    screenWidth = MediaQuery.of(context).size.height;

  if (screenWidth <= smallScreenWidth)
    return 32.0;
  else if (screenWidth <= mediumScreenWidth)
    return 40.0;
  else
    return 48.0;
}
Related