Home > OS >  Flutter: How can I add dynamic number of columns depending on device width or orientation?
Flutter: How can I add dynamic number of columns depending on device width or orientation?

Time:01-31

I have a Flutter app which in one of the pages it presents a list of more than 200 items. How can I make it so that when the app is running in a desktop environment for example it displays more than one column dynamically and that when it runs on phones it displays a single columns or when it run on tablet in vertically orientation it displays one column and more than one column when the device is on horizontal orientation?

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'something here',
            ),
            Text(
              'something here',
            ),
            Text(
              'something here',
            ),
            Text(
              'something here',
            ),
          ],
        ),
      ),
    );
  }
}

This will produce a single column no matter the device or orientation.

CodePudding user response:

Try using GridView instead of Column, in that way you can adjust number of columns with crossAxisCount property of GridView. I am coming to that in a while.

Lets talk about how to adjust the number of columns dynamically depending upon the screen size. For example, I want single column in mobile, 2 columns in tab and 4 columns in desktop.

I'll create an enum named LayoutSize that represents different layout sizes. Also create an extension that returns number of columns depending upon the LayoutSize.

enum LayoutSize { small, medium, large }

extension LayoutSizeX on LayoutSize {
  int get noOfColumns {
    switch (this) {
      case LayoutSize.small:
        return 1;
      case LayoutSize.medium:
        return 2;
      case LayoutSize.large:
        return 4;
    }
  }
}

Now it's time to think about Breakpoints that will represent maximum width for different LayoutSize. You can change the numbers according to your requirements.

abstract class Breakpoints {
  static const double small = 760;
  static const double medium = 1644;
  static const double large = 1920;
}

Finally wrap up all these logic and create the UI. Here LayoutBuilder will serve the purpose of changing the number of columns whenever there is a change in constraints.

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(builder: (context, constraints) {
      final screenWidth = MediaQuery.of(context).size.width;

      if (screenWidth <= Breakpoints.small) {
        return _buildMyWidget(LayoutSize.small);
      }

      if (screenWidth <= Breakpoints.medium) {
        return _buildMyWidget(LayoutSize.medium);
      }

      if (screenWidth <= Breakpoints.large) {
        return _buildMyWidget(LayoutSize.large);
      }

      return _buildMyWidget(LayoutSize.small);
    });
  }

  Widget _buildMyWidget(LayoutSize size) {
    return GridView.builder(
      gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
        crossAxisCount: size.noOfColumns,
      ),
      itemBuilder: (context, index) {
        return Container();
      },
    );
  }
}

I know this solution requires a little bit of extra coding, but believe me this is going to be very much efficient in long run, even in building the whole app responsive, not only a particular widget.

This is the minimal code you need to write in this particular case. But if you're interested in much generic way, here is a link to a gist.

CodePudding user response:

You can check this article about orientation and different sizes. It is what you are looking for.

https://medium.com/flutter-community/developing-for-multiple-screen-sizes-and-orientations-in-flutter-fragments-in-flutter-a4c51b849434

  •  Tags:  
  • Related