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.
