Flutter fill size - flutter

I've a custom widget that I paint as follows
#override
Widget build(BuildContext context) {
return Container(
child: CustomPaint(
painter: MyPainter(),
),
);
}
But that trows an error during painting, namely that the given size is of Size(0,0). When I add hardcoded sizes to the container
return Container(
width: 200,
height: 200,
child: CustomPaint(
painter: MyPainter(),
),
);
Then it gets painted nicely. But I don't want it to be 200x200. I want the width to fill the screen and the height to be as large as the width (i.e. a square width).
I also tried removing the width and height and adding constraints: BoxConstraints.expand() to the container, but to no prevail nor does switching Container for FittedBox.

Related

how to give a widget, a specific width according to its parent - Flutter

there is a scenario that i have a circle and inside that circle i want to show some text. Both items are in a scrollable listview. i want to calculate the width of the parent and then give with to the inner children to be placed and shouldn't move backward or forward from its outer parent circle widget.
i have used stack widget to do so which works fine on a single device or screen but what about other screen sizes?
any suggestion according to this?
I asked yesterday the same concept question:
the FractionallySizedBox is super useful on those cases, it gives the width / height of a children based on the width / height of the parent:
class MyStatelessWidget extends StatelessWidget {
const MyStatelessWidget({super.key});
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: ParentCircle(
height: 250,
width: 250,
color: Colors.red,
child: FractionallySizedBox(
widthFactor: .5,
heightFactor: .5,
alignment: FractionalOffset.center,
child: ChildCircle(),
),
),
),
),
);
}
}
this will give the ChildCircle a 50% width and 50% height of the ParentCircle

Why does a SizedBox in another SizedBox ignore its width and hight?

When I nest two SizedBoxes, the width and height of the inner box are ignored. Why is this, how can I work around it?
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Center(
child: SizedBox(
width: 300,
height: 500,
child: SizedBox(
width: 200, height: 200, child: Container(color: Colors.green)),
));
}
}
In this example, I have a 300x500 sized box and an inner 200x200 SizedBox. In the picture you can see that the green box is the size of the outer SizedBox but should actually be a 200x200 square.
According to flutter documentation: If given a child, this widget forces it to have a specific width and/or height. These values will be ignored if this widget's parent does not permit them. For example, this happens if the parent is the screen (forces the child to be the same size as the parent), or another SizedBox (forces its child to have a specific width and/or height). This can be remedied by wrapping the child SizedBox in a widget that does permit it to be any size up to the size of the parent, such as Center or Align.
So wrapping the child with center would solve the problem:
Center(
child: SizedBox(
width: 300,
height: 500,
child: Center(
child: SizedBox(
width: 200, height: 200, child: Container(color: Colors.green)),
),
)),
The problem is, SizedBox can set widget size only within the constrains set by the parent. Many widgets, like Padding, want their child to occupy 100% of the space available to them. This makes sense, because if the child is smaller they wouldn't know where to put it.
If you want the child to be smaller than the parent you could use Center or Align, e.g. replace
I had the same issue and I solved my problem using the FractionallySizedBox class.
You can specify the suitable size using fractions of the above SizedBox as widthFactor and heightFactor:
Widget build(BuildContext context) {
return SizedBox.expand(
child: FractionallySizedBox(
widthFactor: 0.5,
heightFactor: 0.5,
alignment: FractionalOffset.center,
child: DecoratedBox(
decoration: BoxDecoration(
border: Border.all(
color: Colors.blue,
width: 4),
),
),
),
);
}

How do I allow a Flutter image to overflow the screen?

The following Flutter widget build will show an image on the screen:
#override
Widget build(BuildContext context) {
return Image.asset('assets/images/image.jpg');
}
How do I wrap or configure the Image in order to show a zoomed/scaled version that is allowed to overflow the screen boundaries. Nothing I have tried so far has worked. I would like to set the image to a width of 1.25 times the screen width and then present it as illustrated below.
Wrapping the image in a FittedBox and specifying fit: BoxFit.cover along with setting both width and height for the image will make it work.
#override
Widget build(BuildContext context) {
return FittedBox(
child: Image.asset(
'assets/images/image.jpg',
width: MediaQuery.of(context).size.width * 1.25,
height: 400,
fit: BoxFit.cover,
),
);
}
I think that something like this could be what you are looking for.
Basically giving the width of the image based on your screen size, it is important to notice that it will scale with the screen size, so a tablet might be a problem with respect to a mobile phone
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return ClipRect(
clipBehavior: Clip.hardEdge,
child: Image.asset(
'assets/images/image.jpg',
width: size.width * 1.25,
fit: BoxFit.cover
),
);
}
EDIT: I've tried to run the code myself and it looks like the best solution for this is a Stack, below the code
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Stack(children: [
Positioned(
left: -size.width*0.125,
right: -size.width*0.125,
child: Image.asset(
'assets/images/image.jpg',
),
),
]
);
}

Flutter: layout question regarding column child height

I have a layout where I want to expand a widget (container) to the right, it's the red area in the examples. To the left of the expanded container there is a column with an image at the topleft (blue in examples) and a button in the bottom of the column. I do know the button width, it's a bit over 100 pixels but we can assume that it's 100 pixels if that helps.
The thing is that the blue area (it's a user uploaded image) can vary in size. From e.g. 100x100 to 800x800. It will be square and smaller than 100x100 is not supported. Large images are resized to 800x800.
I want to achieve this:
The column should adapt it's size depending on the image size.
The column should be as wide as needed by the button but otherwise 100 <= width <= 400 depending on image size.
The column should not overflow in any direction.
The red area should be maximized.
The button should always be at the bottom left of the layout.
I cannot know the column height in advance without using a LayoutBuilder and I want to know if this is achievable without calculating the exact height in pixels using a LayoutBuilder.
Here's an example of how I want it too look with a small image (100x100) and that works with the code below the image:
Code that works well for 100x100 image:
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(widget.title)),
body: Center(
child: Container(
height: 400,
width: 800,
child: Row(
children: <Widget>[
_buildColumn(),
Expanded(child: Container(color: Colors.red)),
],
),
),
),
);
}
Widget _buildColumn() {
return Container(
constraints: BoxConstraints(maxWidth: 400),
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
_buildImage(),
MaterialButton(
color: Colors.green,
child: Text('Fixed height button'),
onPressed: () {},
)
],
),
),
);
}
Widget _buildImage() {
// This can vary from 100x100 to 800x800 (always square)
var size = 100.0;
return Container(color: Colors.blue, width: size, height: size);
}
If I bump it to an 800x800 image by changing the size variable to 800.0 in _buildImage() I get this layout:
I understand that the column have unconstrained height on it's children so it will render the blue container with 800px height which creates the overflow. I do know that the column height is 400px in this case and that the button is 48px high so I can calculate that the max image size is 352px in height. By wrapping the blue container in a Container with constraints (maxWidth: 352, maxHeight: 352) I achieve the layout that I want:
Widget _buildImage() {
// This can vary from 100x100 to 800x800 (always square)
var size = 800.0;
return Container(
constraints: BoxConstraints(maxWidth: 352, maxHeight: 352),
child: Container(color: Colors.blue, width: size, height: size),
);
}
I can also achieve this using expanded, like this:
Widget _buildImage() {
// This can vary from 100x100 to 800x800 (always square)
var size = 800.0;
return Expanded(
child: Container(color: Colors.blue, width: size, height: size),
);
}
I want to avoid using calculated pixels for height/width so lets continue with the Expanded widget. When I have that expanded widget with a small image, i.e. 100x100 I get this result (which is not what I want):
I need to align my blue square within the expanded widget to prevent it to getting stretched but when I do that (align top left), like this:
Widget _buildImage() {
// This can vary from 100x100 to 800x800 (always square)
var size = 100.0;
return Expanded(
child: Container(
alignment: Alignment.topLeft,
child: Container(color: Colors.blue, width: size, height: size),
),
);
}
Then I get this result:
The container outside of the blue container expands and makes the column unnecessary wide. I want to have the same look as the first image when I have a small image.
How can I achieve this adaptive layout without using a LayoutBuilder and calculating exact image constraints?
Wrap the column with a container and set the height:
MediaQuery.of(context).size.height * 0.8;
it will contain 80% height in screen

BoxConstraints forces an infinite height

child:Column(
children: <Widget>[
Container(
height: double.infinity,
width: 100.0,
color: Colors.red,
child: Text('hello'),
),)
in this,when i make height:double.infinity,it gives error in run saying **BoxConstraints forces an infinite height.**but when i give height manually it work fine.
can anyone explain me why this happening.
How about this one.
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
children: <Widget>[
Expanded(
child: Container(
// height: double.infinity,
width: 100.0,
color: Colors.red,
child: Text('hello'),
),
),
],
),
),
);
}
}
This means that you can't offer inifite height to the container. It's obvious behaviour if you don't provide the contraints to height.
You have to specify limited height to the container so that flutter can render it, if you offer it infinite it how can flutter render that and up to which constraints it would do that !
Rather you can set double.infinity to width and flutter will successfully render that because by default flutter has constraints for width it will set width to width of screen.
Considering that you have to provide height as that of screen you can use MediaQuery for that
Widget yourMethod(or build)(BuildContext context){
final screenHeight = MediaQuery.of(context).size.height;
return Column(
children:<Widget>[
Container(
height:screenHeight,//but this will be height of whole screen. You need to substract screen default paddings and height of appbar if you have one
width:100.0,
....
)
]);
}
Hope this helps !
Happy coding..
BoxConstraints forces an infinite height
Why This Happens
You're asking to render an infinite height object without a height constraint... Flutter can't do that.
Column lays out children in two phases:
Phase 1: non-Flex items (anything not Expanded, Flexible or Spacer)
done in unconstrained space
Phase 2: Flex items (Expanded,Flexible, Spacer only)
done with remaining space
Phase 1
Column's phase 1 vertical layout is done in unbounded space. That means:
no vertical constraint → no height limit
any widget with infinite height will throw the above error
you can't render an infinite height object in an infinite height constraint... that's goes on forever
Phase 2
after Phase 1 widgets have taken as much space as they intrinsically need, phase 2 Flex items share the remaining/leftover space
the remaining space is calculated from incoming constraints minus Phase 1 widgets dimensions
double.infinity height will expand to use up the remaining space
Infinite Height is OK
Here's an example of using infinite height on a Container inside a Column, which is fine:
class ColumnInfiniteChildPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
children: [
Flexible(
child: Container(
height: double.infinity, // ← perfectly fine
child: Text('Column > Container > Text')),
),
Text('Column > Text')
],
),
),
);
}
}
Remove the Flexible and the error will be thrown.