Flutter set widget position exactly center of the screen - flutter

I want to put a container widget in the middle of the device screen. However, since I used the SizedBox() and SvgPicture.asset() widgets before that, the container does not come right in the middle of the device. How can I do this?
This is my code:
class CenterWidget extends StatefulWidget {
const CenterWidget({Key? key}) : super(key: key);
#override
_CenterWidgetState createState() => _CenterWidgetState();
}
class _CenterWidgetState extends State<CenterWidget> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 30),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: [
const SizedBox(height: 56),
SvgPicture.asset(ImageConstants.instance.logoSvg,
width: (MediaQuery.of(context).size.width - 60) / 2),
Expanded(
child: Center(
child: Container(
color: Colors.red,
width: 100,
height: 100,
),
),
),
],
),
),
),
);
}
}

Use a top center aligned stack, and put the widget you want to be centered within a Positioned.fill widget. You can put the spacer and logo in their own column to keep them arranged vertically:
class _CenterWidgetState extends State<CenterWidget> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 30),
child: Stack(
alignment: Alignment.topCenter,
children: [
Column(
children: [
const SizedBox(height: 56),
SvgPicture.asset(ImageConstants.instance.logoSvg,
width: (MediaQuery.of(context).size.width - 60) / 2),
],
),
Positioned.fill(
child: Center(
child: Container(
color: Colors.red,
width: 100,
height: 100,
),
),
),
],
),
),
),
);
}
}

Related

I can't display 4 Card in middle of page with Flutter

import 'package:flutter/material.dart';
class CardNote extends StatelessWidget {
const CardNote({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: const [
Card(
elevation: 3,
color: Colors.amber,
child: SizedBox(
width: 200,
height: 200,
child: Center(
child: Text(
'Card 1',
)),
),
),
Card(
elevation: 3,
color: Colors.amber,
child: SizedBox(
width: 200,
height: 200,
child: Center(
child: Text(
'Card 2',
)),
),
),
],
),
),
),
);
}
}
When I add this widget to the page where I want to show the cards, I can show 2 widgets in a single line. Then when I call the same widget again, I get the following error.
RenderCustomMultiChildLayoutBox object was given an infinite size during layout.This probably means that it is a render object that tries to be as big as possible, but it was put inside another render object that allows its children to pick their own size.
return Scaffold(
body: Container(
child: Row(
children: const [
CardNote(),
SizedBox(
height: 50,
),
CardNote()
],
),
),
);
This is how I add the cards to the page I want to show.
This is how I want to show 4 cards in the middle of the page
This is how it looks on my page. It shows at the top of the page, not in the middle.
You can wrap your CardNote widget with Expanded widget. And use a top level scrollable widget. Also you dont need to us multiple scaffold
home: Scaffold(
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: const [
CardNote(),
SizedBox(
height: 50,
),
CardNote(),
],
),
),
),
While the card is fixed width, you can provide it
class CardNote extends StatelessWidget {
const CardNote({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Center(
child: Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: const [
Card(
elevation: 3,
color: Colors.amber,
child: SizedBox(
width: 200,
height: 200,
child: Center(
child: Text(
'Card 1',
)),
),
),
Card(
elevation: 3,
color: Colors.amber,
child: SizedBox(
width: 200,
height: 200,
child: Center(
child: Text(
'Card 2',
)),
),
),
],
),
),
);
}
}
You are trying to add a row which has alignment of spaceEven inside another row. When you added the first set of cards it got aligned evenly. On second set you have 2 set of rows inside a row each one has alignment of spaceEven..
Depending on the layout if you wish to show these cards one below the other set then use a Column widget
return Scaffold(
body: Container(
child: Column(//here
children: const [
CardNote(),
SizedBox(
height: 50,
),
CardNote()
],
),
),
);

SingleChildScrollView rendering overflow when viewport greater than maxwidth

I'm trying to set web content to have a maximum width (the orange in the image), and always fill the available height, which I've achieved.
However when the window is wider than the maximum content width, and the window height is less than the height of the content, header, and footer combined. I'm getting a rendering overflow.
When what I'm after is for content to hold it's height, and the scroll to enable.
Note: the problem seems to go way if each text is only 1 line worth.
I've tried using CustomeScrollView with a SliverFillRemaining, but I get the same problem.
Any assistance would be greatly appreciated.
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 const MaterialApp(
title: 'Scrollable Layout',
home: ScrollableLayout(),
);
}
}
class ContentWidthContainer extends StatelessWidget {
final Widget child;
const ContentWidthContainer({Key? key, required this.child})
: super(key: key);
#override
Widget build(BuildContext context) {
return Container(
color: Colors.grey,
child: Align(
alignment: Alignment.topCenter,
child: Container(
color: Colors.orange,
width: double.infinity,
constraints: const BoxConstraints(
maxWidth: 960,
),
padding: const EdgeInsets.symmetric(horizontal: 75),
child: child),
),
);
}
}
class ScrollableLayout extends StatelessWidget {
const ScrollableLayout({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return DefaultTextStyle(
style: Theme.of(context).textTheme.bodyText2!,
child: LayoutBuilder(
builder: (BuildContext context, BoxConstraints viewportConstraints) {
return SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: viewportConstraints.maxHeight,
),
child: IntrinsicHeight(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
ContentWidthContainer(
child: Container(
color: Colors.indigo,
height: 200,
child: const Text('Header: Fixed Height')),
),
Expanded(
child: ContentWidthContainer(
child: Container(
color: Colors.white,
child: Column(
children: const [
Text(
'ContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContent'),
Text('Content'),
Text('Content'),
Text('Content'),
Text('Content'),
Text('Content'),
Text('Content'),
],
)),
),
),
ContentWidthContainer(
child: Container(
color: Colors.indigo,
height: 200,
child: const Text('Footer: Fixed Height')),
),
],
),
),
),
);
},
),
);
}
}
If the height of the header and footer is 200 each, then the height of the middle content should be less than 400.
height: MediaQuery.of(context).size.height - 400
Therefore change your code to
#override
Widget build(BuildContext context) {
return DefaultTextStyle(
style: Theme.of(context).textTheme.bodyText2!,
child: LayoutBuilder(
builder: (BuildContext context, BoxConstraints viewportConstraints)
{
return SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: viewportConstraints.maxHeight,
),
child: IntrinsicHeight(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
ContentWidthContainer(
child: Container(
color: Colors.indigo,
height: 200,
child: const Text('Header: Fixed Height')),
),
Expanded(
child: ContentWidthContainer(
child: Container(
height: MediaQuery.of(context).size.height - 400,
color: Colors.white,
child: Column(
children: const [
Text(
'ContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContent'),
Text('Content'),
Text('Content'),
Text('Content'),
Text('Content'),
Text('Content'),
Text('Content'),
],
)),
),
),
ContentWidthContainer(
child: Container(
color: Colors.indigo,
height: 200,
child: const Text('Footer: Fixed Height')),
),
],
),
),
),
);
},
),
);
}
On changing it to use a Column, with just 2 children, and the alignment set to SpaceBetween, the overflow problem disappears when you make the window width but shorter than the content.
class ScrollableSpaceBetweenLayout extends StatelessWidget {
const ScrollableSpaceBetweenLayout({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return DefaultTextStyle(
style: Theme.of(context).textTheme.bodyText2!,
child: LayoutBuilder(
builder: (BuildContext context, BoxConstraints viewportConstraints) {
return SingleChildScrollView(
child: Container(
color: Colors.black12, // the background / sides
constraints: BoxConstraints(
minHeight: viewportConstraints.maxHeight,
),
child: Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Container(
color: Colors.indigo,
height: 200,
child: const Align(
alignment: Alignment.center,
child: Text('Header: Fixed Height'))),
Container(
color: Colors.orange,
constraints: BoxConstraints(
maxWidth: 960,
minHeight: max(viewportConstraints.maxHeight - 400, 0),
),
padding: const EdgeInsets.symmetric(horizontal: 75),
child: Container(
color: Colors.white,
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
children: const [
Text(
'ContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContent'),
Text('Content'),
Text('Content'),
Text('Content'),
Text('Content'),
Text('Content'),
Text('Content'),
],
),
Container(
child: const Text('spacer'),
height: 1,
color: Colors.red)
],
)),
),
Container(
color: Colors.indigo,
height: 200,
child: const Align(
alignment: Alignment.center,
child: Text('Footer: Fixed Height'))),
],
),
),
);
},
),
);
}
}

How expanded widget works in flutter?

I have a simple code which produces design like this
This is my code
This is my code for the design:
class InputPage extends StatefulWidget {
#override
_InputPageState createState() => _InputPageState();
}
class _InputPageState extends State<InputPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('BMI CALCULATOR'),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Expanded(
child: Row(
children: [
Expanded(
child: ReusableCard(colour: Color(0xff1d1e33),)
),
Expanded(
child: ReusableCard(colour: Color(0xff1d1e33),)
),
],
),
),
Expanded(
child: ReusableCard(colour: Color(0xff1d1e33)),
),
Expanded(
child: Row(
children: [
Expanded(
child: ReusableCard(colour: Color(0xff1d1e33),)
),
Expanded(
child: ReusableCard(colour: Color(0xff1d1e33),)
),
],
),
),
Container(
width: double.infinity,
height: 100,
color: Colors.pink,
)
],
),
);
}
}
Now when I remove the parent expanded widget, I get a design like this:
Here is the code for this design:
class _InputPageState extends State<InputPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('BMI CALCULATOR'),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Row(
children: [
Expanded(
child: ReusableCard(colour: Color(0xff1d1e33),)
),
Expanded(
child: ReusableCard(colour: Color(0xff1d1e33),)
),
],
),
Expanded(
child: ReusableCard(colour: Color(0xff1d1e33)),
),
Row(
children: [
Expanded(
child: ReusableCard(colour: Color(0xff1d1e33),)
),
Expanded(
child: ReusableCard(colour: Color(0xff1d1e33),)
),
],
),
Container(
width: double.infinity,
height: 100,
color: Colors.pink,
)
],
),
);
}
}
What is the reason for this? Even if I remove for the parent I have added expanded for the child, so shouldn't it be the same?
ReusableCard:
class ReusableCard extends StatelessWidget{
final Color colour;
ReusableCard({#required this.colour});
#override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.all(15),
decoration: BoxDecoration(
color: colour,
borderRadius: BorderRadius.circular(20)
),
);
}
}
Basically The Expanded widget will expand to all of the remaining height the parent widget have,
So you in the first code, in your body inside the column we have 4 widgets
Expanded(
child: Row(
),
),
Expanded(
child: ReusableCard(colour: Color(0xff1d1e33)),
),
Expanded(
child: Row(
),
),
Container(
width: double.infinity,
height: 100,
color: Colors.pink,
)
So lets say that the height of the parent widget is 1000, the
height of the container at the end is fixed so it will always take 100, so 900 is left
The three expanded widget in the column will take the remaining 900, and because you did not specify any flex property in the Expanded widget all of them will receive same height so 900/3 = 300 for each widget.
in the second code inside the column you have
Row(
),
Expanded(
child: ReusableCard(colour: Color(0xff1d1e33)),
),
Row(
),
Container(
width: double.infinity,
height: 100,
color: Colors.pink,
)
again assuming the height available is 1000, the container is fixed height of 100 so 900 is left, now the expanded widget will take all of the available height which is 900 because the rows don't have any fixed height.
the Expanded widget inside the Rows will make the card inside them expand to the parent height, but the parent row does not have any height (0 height) so it will expand to this 0 height which is useless.
always keep it in mind that the Expanded will take the height or width from its parent widget.

How to make this in Flutter i am new in flutter so if anyone knows

I want one row with this one big image on left and two images on right with one up and the second down.
thanks in advance if Someone can help!!
The key insight is to break the layout into nested rows and/or columns. Check out this example,
import 'package:flutter/material.dart';
void main() {
runApp(App());
}
class App extends StatefulWidget {
#override
_AppState createState() => _AppState();
}
class _AppState extends State<App> {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.white,
body: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(
child: getContainer(Colors.green),
),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(
child: getContainer(Colors.yellow),
),
Expanded(
child: getContainer(Colors.red),
)
],
),
),
],
),
),
);
}
}
Widget getContainer(MaterialColor color) =>
Container(height: 50, width: 50, color: color);
Everything is contained in one row, the first column will be larger than the second one with the widget Expanded flex :1. In the second column, there's a column widget with that you'll have two rows for your image.
import 'package:flutter/material.dart';
class Home extends StatelessWidget {
const Home({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: Row(
children: [
Expanded(
child: SizedBox(
child: Image.asset('your large image'),
),
flex: 1,
),
Expanded(
child: Column(
children: [
Image.asset('your second image'),
Image.asset('your third image'),
],
),
flex: 0,
)
],
),
),
);
}
}
solved
**here is the example **
import 'package:flutter/material.dart';
class BagScreen extends StatelessWidget {
const BagScreen({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
// color: Colors.red,
height: 400,
width: 400,
child: Row(
children: [
Container(
child: Image.asset(
"assets/images/bgimage.PNG",
fit: BoxFit.contain,
width: 250.0,
// height: 350.0,
),
),
SizedBox(
width: 10.0,
),
Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
SizedBox(
height: 10.0,
),
Container(
child: Image.asset("assets/images/upsm.PNG"),
),
Container(
child: Image.asset("assets/images/upsm.PNG"),
),
],
)
],
),
),
),
);
}
}

is there a way to embed a SingleChildScrollView (Vertical) within another SingleChildScrollView(Horizontal) in Flutter

In my app there is a SingleChildScrollView(with scrollable direction as Horizontal) which has a N number of containers.
Is there a way to embed a the SingleChildScrollView(with scrollable direction as Horizontal) into a SingleChildScrollView (with scrollable direction as Vertical) in Flutter.
for example:
class HomeBody extends StatelessWidget {
#override
Widget build(BuildContext context) {
return SafeArea(
child: Padding(
padding: sidePadding,
child: Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
HomeAppbar(),
addVerticalSpace(15),
Text(
'Welcome, Jack',
style: themeData.textTheme.headline1,
),
addVerticalSpace(15),
SearchField(
width: mediasize.width - 2 * screenHorizontalPadding,
height: mediasize.height,
),
addVerticalSpace(25),
//I want to add a SingleChildScrollView (Vertical Direction) from this point to
TitleMoreBar(barTitle: 'Trending'),
addVerticalSpace(15),
//the FullProductCardHorizontalList() has a SingleChildScrollView(Horizontal direction)
FullProductCardHorizontalList(),
addVerticalSpace(25),
TitleMoreBar(barTitle: 'Popular Brands'),
addVerticalSpace(25),
//the BrandCardList() has a SingleChildScrollView(Horizontal direction)
BrandCardList(),
// this where the SingleChildScrollView (Vertical) should end
],
),
),
),
);
}
Yes, you can do this like:
import 'package:flutter/material.dart';
class ScrollTraining extends StatefulWidget {
#override
_ScrollingTraining createState() => _ScrollingTraining();
}
class _ScrollingTraining extends State<ScrollTraining> {
double mWidth;
#override
Widget build(BuildContext context) {
mWidth = MediaQuery.of(context).size.width;
return Scaffold(
appBar: AppBar(),
body: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: mWidth,
height: 400,
color: Colors.indigo,
margin: EdgeInsets.symmetric(vertical: 8.0),
alignment: Alignment.center,
child: Text("Fixed Box"),
),
Container(
width: mWidth,
height: 200,
margin: EdgeInsets.symmetric(vertical: 8.0),
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: getChildren(),
),
),
),
Container(
width: mWidth,
height: 400,
color: Colors.brown,
margin: EdgeInsets.symmetric(vertical: 8.0),
alignment: Alignment.center,
child: Text("Fixed Box"),
),
Container(
width: mWidth,
height: 200,
margin: EdgeInsets.symmetric(vertical: 8.0),
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: getChildren(),
),
),
),
],
),
),
);
}
List<Widget> getChildren() {
List<Widget> output = List();
List<Color> colorList = [
Colors.redAccent,
Colors.deepOrange,
Colors.orangeAccent,
Colors.yellow,
Colors.lightGreenAccent,
Colors.green,
Colors.greenAccent,
Colors.blue,
Colors.purpleAccent,
Colors.pink,
];
for (int i = 0; i < 10; i++) {
output.add(Container(
width: 140,
height: 200,
color: colorList[i],
));
}
return output;
}
}
I hope it is useful for you.