Flutter - How to setup a custom height and width of Scaffold - flutter

I'm aware that MediaQuery solutions exist to problems, however, I want to limit the size of my Scaffold so that it can be used for web-based apps as well. Similar to what Instagram has, can anyone help me with it?

Have you tried wrapping your Scaffold in SafeArea with a minimum property of EdgeInsets.all(32.0)?
For me, this recreates your mockup on any screen
Example code:
//...
return SafeArea(
minimum: const EdgeInsets.all(32.0),
child: Scaffold(
//...
),
);
//...

I used sizedboxes to create layers for a single page look. The gridview does not shrink to the size of the window. Instead it activates scrolling. My solution works for chrome web.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.purple,
buttonTheme: const ButtonThemeData(
textTheme:ButtonTextTheme.primary,
buttonColor:Colors.yellow,
)
),
home: Test_SinglePage(),
);
}
}
class DataRecord{
String name;
String number;
DataRecord(this.name,this.number);
}
class Test_SinglePage extends StatefulWidget {
Test_SinglePage({Key? key}) : super(key: key);
#override
State<Test_SinglePage> createState() => _Test_SinglePageState();
}
class _Test_SinglePageState extends State<Test_SinglePage> {
List<DataRecord> lstData=[
DataRecord("A","1"), DataRecord("B","2"), DataRecord("C","3"), DataRecord("D","4"),
DataRecord("E","5"), DataRecord("F","6"), DataRecord("G","7"), DataRecord("H","8"),
DataRecord("I","9"), DataRecord("J","10"), DataRecord("K","11"), DataRecord("L","12"),
DataRecord("M","13"), DataRecord("N","14"), DataRecord("O","15"), DataRecord("P","16"),
DataRecord("Q","17"), DataRecord("R","18"), DataRecord("S","19"), DataRecord("T","20"),
DataRecord("V","21"), DataRecord("X","22"), DataRecord("Y","23"), DataRecord("Z","24"),
];
Widget _dialogBuilder(BuildContext context, String name)
{
return SimpleDialog(
contentPadding:EdgeInsets.zero,
children:[
Container(width:80,height:80,child:
Column(children:[
Text(name),
SizedBox(height:20),
Expanded(child:Row(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
children: [ElevatedButton(onPressed:(){ Navigator.of(context).pop();}, child:
Text("Close"))
],))
])
)]);
}
Widget _itemBuilder(BuildContext context,int index)
{
return
GestureDetector(
onTap:()=>showDialog(context:context,builder:(context)=>_dialogBuilder(context,lstData[index].name)),
child:Container(color:Colors.grey,child:GridTile(child: Center(child:
Column(children:[
Text(lstData[index].name,style:Theme.of(context).textTheme.headline2),
Text(lstData[index].number,style:Theme.of(context).textTheme.headline4)
])
))));
}
#override
Widget build(BuildContext context) {
return Scaffold(appBar: AppBar(title:Text("Single Page")),body:
Container(
margin: const EdgeInsets.only(top:20.0, left: 20.0, right: 20.0, bottom:10.0),
child:
Flex(
direction: Axis.vertical,
mainAxisAlignment: MainAxisAlignment.start,
children: [
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child:Row(
mainAxisAlignment: MainAxisAlignment.start,
children:[
FittedBox(
fit:BoxFit.fitHeight,
child:SizedBox(
width:200,
height:200,
child: Image.asset("assets/images/apple.jpg"),
)),
Column(
mainAxisAlignment:MainAxisAlignment.start,
children:[
Row(
children: [
SizedBox(height:100,width:200,child:Container(color:Colors.red,child:Text("reached"))),
SizedBox(height:100,width:200,child:Container(color:Colors.blue,child:Text("reached2"))),
SizedBox(height:100,width:200,child:Container(color:Colors.green,child:Text("reached3")))
],),
Row(children: [
SizedBox(width:600, child:ElevatedButton(
onPressed:(){
},child:Text("Press Me")))],)
])
])),
Expanded(child:SizedBox(
height:400,
width:MediaQuery.of(context).size.width,child:
GridView.builder(
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 300,
childAspectRatio: 3 / 2,
crossAxisSpacing: 20,
mainAxisSpacing: 20),
itemCount: lstData.length,
itemBuilder: _itemBuilder
)))],)
,));
}
}

Related

How to make two containers within one column scrollable?

I am building an app using Flutter, and I encountered this mistake:
I am making a column, that has two Containers inside it. The top Container has a fixed height, 40% of screen. The bottom Container's height is changed. Its height is dependent on the amount of containers it has inside. If the amount of inner containers is more than 6, then I have an overflow. Yet, I want a scrollable behavior (only on second widget). This is the minimal reproducible code:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Stateful Clicker Counter',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Clicker Counter Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
final String title;
const MyHomePage({Key? key, required this.title}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
width: size.width,
height: size.height * 0.4,
color: Colors.black,
),
Container(
width: size.width,
color: Colors.red,
child: Column(
children: [
Text("Hello"),
GridView.count(
crossAxisCount: 3,
children: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((el) => Text(el.toString())).toList() as List<Widget>,
shrinkWrap: true,
),
],
)),
],
),
));
}
}
As you may see, I use GridView.count in the second container to create this inner containers. It has by default scrollable behaviour. But it still gives overflow. How do I fix this?
GridView has scroll behavior but when using shrinkWarp scrolling doesn't work.
as on https://youtu.be/LUqDNnv_dh0?t=117 when defination shrinkWarp:
to completely evaluate itself and figure out its full size up front and then proceed by your top-level viewport behaving as if they're all just one widget
that means when using shrinkWarp gridview will take a full size.
you can solve your code by doing like:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Stateful Clicker Counter',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Clicker Counter Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
final String title;
const MyHomePage({Key? key, required this.title}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
width: size.width,
height: size.height * 0.4,
color: Colors.black,
),
Expanded( // Added
child: Container(
width: size.width,
color: Colors.red,
child: Column(
children: [
Text("Hello"),
Expanded( // Added
child: GridView.count(
crossAxisCount: 3,
children: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((el) => Text(el.toString())).toList() as List<Widget>,
// shrinkWrap: true, // changed
),
),
],
)),
),
],
),
));
}
}
You should wrap your main column in an expanded or flexible format so that it uses the available screen space. Then add a SingleChildScrollView on your child column to get a simple scroll.
Example:
Expanded(
child:
Container(
width: size.width,
color: Colors.red,
child: SingleChildScrollView(
child: Column(
children: [
Text("Hello"),
GridView.count(
crossAxisCount: 3,
children: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((el) => Text(el.toString())).toList() as List<Widget>,
shrinkWrap: true,
),
],
)
),
)
)
wrap your second Container & column with expanded and remove shrinkwrap from GridView.count:
Expanded(
// Added
child: Container(
width: size.width,
color: Colors.red,
child: Column(
children: [
Text("Hello"),
Expanded(
// Added
child: GridView.count(
crossAxisCount: 3,
children: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
.map((el) => Text(el.toString()))
.toList() as List<Widget>,
// shrinkWrap: true, // changed
),
),
],
)),
),

I am new to flutter and I think I have misunderstood the widget and layout system

If I want to add more buttons and text widgets where and how should I do it, should I make some sort of column and row system or am I totally off? And is my code programmed wrong?
import 'package:flutter/material.dart';
void main() {
runApp(
const HomeScreen(),
);
}
class HomeScreen extends StatelessWidget {
const HomeScreen({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Dice'),
centerTitle: true,
),
body: const Dice()));
}
}
class Dice extends StatefulWidget {
const Dice({Key? key}) : super(key: key);
#override
State<Dice> createState() => _DiceState();
}
class _DiceState extends State<Dice> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Row(
children: [
Expanded(
child: Container(
margin: const EdgeInsets.all(15),
child: Image.asset('images/1.png'))),
Expanded(
child: Container(
margin: const EdgeInsets.all(15),
child: Image.asset('images/2.png'))),
Expanded(
child: Container(
margin: const EdgeInsets.all(15),
child: Image.asset('images/3.png'))),
Expanded(
child: Container(
margin: const EdgeInsets.all(15),
child: Image.asset('images/4.png'))),
Expanded(
child: Container(
margin: const EdgeInsets.all(15),
child: Image.asset('images/5.png')))
],
),
));
}
}
I am going to add variables to the children in the container later.
For better understanding I would recommend you checking out this medium article. https://medium.com/flutter-community/flutter-layout-cheat-sheet-5363348d037e Here you can view all the important layout widgets you can use.
In general you have a widget tree starting by MaterialApp and you can add as many items as you want. In flutter if you want multiple widgets you can use Row and Column for that. Both of them provides a children property in brackets [] there you can add multiple widgets inside separated by comma.
Most of the other widgets are also able to provide a children property where you can add even more children widgets. That's how the widget tree in general works. Actually you have unlimited possibility’s.
Your code is totally fine. By the way you can also create custom widgets if the plenty widgets of flutter doesn't fit your use case.
In your example you can add whatever you want in your row, text, more images, buttons, everything you like.
Here you can check out the official widget catalog of flutter: https://docs.flutter.dev/development/ui/widgets
You can place a Column/ListView in between your Center and Row widgets, then you could add multiple rows to it like below:
class _DiceState extends State<Dice> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
children: [
Row(
children: [
Expanded(
child: Container(
margin: const EdgeInsets.all(15),
child: Image.asset('images/1.png'))),
Expanded(
child: Container(
margin: const EdgeInsets.all(15),
child: Image.asset('images/2.png'))),
Expanded(
child: Container(
margin: const EdgeInsets.all(15),
child: Image.asset('images/3.png'))),
Expanded(
child: Container(
margin: const EdgeInsets.all(15),
child: Image.asset('images/4.png'))),
Expanded(
child: Container(
margin: const EdgeInsets.all(15),
child: Image.asset('images/5.png')))
],
),
Row(children: [/* more content here */]),
],
),
),
);
}
}

Can't set a GridView in a Column

I need to set many items into a grid view. But I need to write something above the grid view and that's why I need a column which contains the texts and the grid view. But If I set some text and below the grid view then it doesn't work. Here is my code:
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Hamim Shop',
home: Scaffold(
body: Container(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Text('Hamim Shop'),
GridView.count(
crossAxisCount: 3,
children: List.generate(choices.length, (index) {
return Center(
child: ChoiceCard(choice: choices[index]),
);
}),
),
],
),
),
),
);
}
}
Edited from Here:
Choice Card:
class ChoiceCard extends StatelessWidget {
const ChoiceCard({Key key, this.choice}) : super(key: key);
final Choice choice;
#override
Widget build(BuildContext context) {
return Card(
color: Colors.white,
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(child: Icon(choice.icon, size: 150)),
Text(choice.title),
]),
));
}
}
...
class Choice {
const Choice({this.title, this.icon});
final String title;
final IconData icon;
}
const List<Choice> choices = const [
const Choice(title: 'Car', icon: Icons.directions_car),
.....
];
Use shrinkwrap:true & physics:NeverScrollableScrollPhysics()
physics:
Scroll physics that does not allow the user to scroll. Means only Column+SingleChildScrollView Scrolling work.
shrinkwrap:
If you do not set the shrinkWrap property, your GridView will be as big as its parent.
If you set it to true, the GridView will wrap its content and be as big as its children allow it to be.
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Hamim Shop',
home: Scaffold(
body: Container(
padding: const EdgeInsets.all(8.0),
child: SingleChildScrollView(
child: Column(
children: [
Text('Hamim Shop'),
GridView.count(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
crossAxisCount: 3,
children: List.generate(choices.length, (index) {
return Center(
child: ChoiceCard(choice: choices[index]),
);
}),
),
],
),
),
),
),
);
}
}
class ChoiceCard extends StatelessWidget {
const ChoiceCard({Key key, this.choice}) : super(key: key);
final Choice choice;
#override
Widget build(BuildContext context) {
return Card(
color: Colors.white,
child: Center(
child: Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(child: Icon(choice.icon, size: 150)),
Text(choice.title),
]),
));
}
}
class Choice {
const Choice({this.title, this.icon});
final String title;
final IconData icon;
}
const List<Choice> choices = const [
const Choice(title: 'Car', icon: Icons.directions_car),
....
];

Gridview wrap content flutter

I have a json, I want to display it in gridview, the json has many content, in gridview I just want to show only 9 items.
The problem was I want to wrap the content of the gridview but I dont know how.
I tried wrap widget. If its not possible then I guess I'll reconsider using columns and row for this one.
Please check the code below.
class ServicesWidget extends StatefulWidget {
#override
_ServicesState createState() => _ServicesState();
}
class _ServicesState extends State<ServicesWidget> {
#override
Widget build(BuildContext context) {
return Flexible(
child: GridView.count(
crossAxisCount: 3,
childAspectRatio: 1,
children: <Widget>[
Center(child: Text('qwe')),
Center(child: Text('qwe')),
Center(child: Text('qwe')),
Center(child: Text('qwe')),
Center(child: Text('qwe')),
Center(child: Text('qwe')),
Center(child: Text('qwe')),
Center(child: Text('qwe')),
Center(child: Text('qwe')),
],
),
);
}
}
class HomeScreen extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<HomeScreen> {
#override
Widget build(BuildContext context) {
return DirectSelectContainer(
child: Scaffold(
appBar: AppBar(
title: Row(
children: <Widget>[
// cityDirectSelect(),
// areaDirectSelect(),
Spacer(flex: 1),
IconButton(
padding: EdgeInsets.all(0),
icon: Icon(Icons.person),
color: Colors.grey,
onPressed: () {
Get.off(LoginScreen());
},
)
],
),
),
body: Center(
child: Container(
child: Column(
children: <Widget>[
ServicesWidget(),
Container(
width: double.infinity,
child: Text('qweqwe'),
color: Colors.red,
)
],
),
),
)),
);
}
}
I solve it using shrinkWrap. Now the gridview height is wrapped according to its children.shrinkwrap gridview

How to do a GridView with two crossAxisCount in Flutter?

This is the example of expected output
For the first row, the crossAxisCount will be 3 and the second row, the crossAxisCount will be 2.
GridView.builder(
physics: NeverScrollableScrollPhysics(),
gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
childAspectRatio: 0.75,
mainAxisSpacing: 2.0,
crossAxisSpacing: 1.0,
),
itemCount: int.parse(snapshot.data.result[num].collected),
itemBuilder:
(BuildContext context, int i) {
return Image.asset(
'assets/coin.png');
}),
You can set crossAxisCount to 1 and childAspectRatio to number you need, I use 2
In itemBuilder check index is Odd and return Row with 2 or 3 asset icon
You can copy paste run full code below
code snippet
GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 1, childAspectRatio: 2),
itemCount: _icons.length,
itemBuilder: (context, index) {
if (index.isOdd) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Container(
child: Image.asset('assets/coin.png'),
),
Container(
child: Image.asset('assets/coin.png'),
),
Container(
child: Image.asset('assets/coin.png'),
),
],
);
} else {
working demo
full code
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(flex: 1, child: InfiniteGridView()),
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
class InfiniteGridView extends StatefulWidget {
#override
_InfiniteGridViewState createState() => new _InfiniteGridViewState();
}
class _InfiniteGridViewState extends State<InfiniteGridView> {
List<IconData> _icons = [];
#override
void initState() {
_retrieveIcons();
}
#override
Widget build(BuildContext context) {
return GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 1, childAspectRatio: 2),
itemCount: _icons.length,
itemBuilder: (context, index) {
if (index.isOdd) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Container(
child: Image.asset('assets/coin.png'),
),
Container(
child: Image.asset('assets/coin.png'),
),
Container(
child: Image.asset('assets/coin.png'),
),
],
);
} else {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Container(
child: Image.asset('assets/coin.png'),
),
Container(
child: Image.asset('assets/coin.png'),
),
],
);
}
});
}
void _retrieveIcons() {
Future.delayed(Duration(milliseconds: 200)).then((e) {
setState(() {
_icons.addAll([
Icons.ac_unit,
Icons.airport_shuttle,
Icons.all_inclusive,
Icons.beach_access,
Icons.cake,
Icons.free_breakfast
]);
});
});
}
}