Flutter fill available space in scroll view - flutter

In the following code I have a SingleChildScrollView, I used ConstrainedBox to set a minHeight for its content
I want to force blue content to fill available space, I cannot use Expanded because we are in scroll view, As I? set minHeight before we can determine the available space some how
Actually I want to set a minHeight constraint to blue container, here red container has height: 500 but in real case it is unknown
make blue container as big as possible if device height it big enough and we have no scroll
it device height is not big enough, and we have scroll, set height of blue box as is (auto)
import 'package:flutter/material.dart';
final Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new LayoutBuilder(
builder: (BuildContext context, BoxConstraints viewportConstraints) {
return SingleChildScrollView(
child: ConstrainedBox(
constraints:
BoxConstraints(minHeight: viewportConstraints.maxHeight),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
color: Colors.green[300],
height: 500,
child: Placeholder(),
),
Container(
color: Colors.blue[300],
child: Text('Expand me!'),
),
],
),
),
);
},
);
}
}

You need to wrap column with IntrinsicHeight.

A solution is to use CustomScrollView with SliverFillRemaining passing hasScrollBody false. It's not necessary to use LayoutBuilder and IntrinsicHeight.
CustomScrollView(
slivers: [
SliverFillRemaining(
hasScrollBody: false,
child: Column(
children: [
Container(
color: Colors.green[300],
height: 500,
child: const Placeholder(),
),
Expanded(
child: Container(
color: Colors.blue[300],
height: 100 //set your min height
child: const Text('Expand me!'),
),
),
],
),
)
],
),

Related

Flutter: Adjust Text widget to parent without undesired font paddings

I'm trying to center both texts, and for the T text to take as much height as possible from the parent so the only space remaining will be the container's paddings.
The code:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() {
runApp(TestApp());
}
class TestApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
// Remove status bar
SystemChrome.setEnabledSystemUIOverlays([]);
return MaterialApp(
home: Scaffold(
body: _body(),
),
);
}
Widget _body() => Container(
width: 200,
height: 200,
padding: EdgeInsets.all(16),
color: Colors.lightBlueAccent,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: Container(
color: Colors.lightGreen,
child: FittedBox(
fit: BoxFit.contain,
child: Text("T"),
),
),
),
Flexible(
child: Text("subtitle"),
)
],
),
);
}
As you can see in the screenshot there are undesired paddings in the T text:

How can I set two container on top of each other?

im trying to set 2 containers on top of each other. What I want is to showing a star and when user pressed the star I wanna open 5 star so he can vote . Im not really sure if im thinking the correct way . But fr that I wanna create one container and in another container directly above this stars container displaying all other buttons how's just buttons to clock normally . I hope that you understand what I trying to do. So when im putting the star container also in the same container they buttons when opening all stars the whole container will move isn't?
So heres im trying to do.
class VideoPage extends StatelessWidget {
static const route = '/Video';
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Container(
height: 100,
color: Colors.yellow[300],
),
Expanded(
child: Row(
children: [
Expanded(
child: Container(color: Colors.green[300]),
),
Container(
width: 100,
color: Colors.orange[300],
),
Container(
width: 100,
color: Colors.red[300],
),
],
),
),
Container(
height: 80,
color: Colors.blue[300],
),
],
),
);
}
}
This look like that:
And I want that the orange one is directly under the red one so there will be first one star and on pressing it open 5 stars . Is this possible what im trying ? If so please help . If not please help haha
What you need to use is the Stack Widget:
Stack(
children: <Widget>[
BottomWidget(),
MiddleWidget(),
TopWidget(),
],
),
The last widget of the children is the top layer, structure descending.
more info: https://medium.com/flutter-community/a-deep-dive-into-stack-in-flutter-3264619b3a77
EDIT:
In your case if you want the orange one underneath, you have to do some changes within your structure and split it from your Row()
Example
import 'package:flutter/material.dart';
final Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Container(
height: 100,
color: Colors.yellow[300],
),
Stack(
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width *1,
height: 200,
color: Colors.orange,
),
Container(
height:200,
child: Row(
children: [
Expanded(
child: Container(color: Colors.green[300]),
),
Container(
width: 100,
color: Colors.red.withOpacity(0.5),
),
],
)),
],
),
Container(
height: 80,
color: Colors.blue[300],
),
],
),
);
}
}

Flutter full width Container

I am trying to make Container full width but its not working
void main() {
runApp(MaterialApp(
title: "Practice",
home: Column(
children: <Widget>[
Row(
children: <Widget>[
Container(
decoration:
BoxDecoration(border: Border.all(color: Colors.blueAccent)),
child: Text("My Awesome Border"),
)
],
),
],
),
));
}
this is output in browser
I have couple of more questions
Why color of text is Red and size is big?
How there is a yellow line under text?
Update
Resolved issue with MediaQuery. Here is full working code for future readers.
void main() {
runApp(MaterialApp(
title: "Practice",
home: Scaffold(
body: MyHomeScreen(),
)));
}
class MyHomeScreen extends StatelessWidget {
const MyHomeScreen({
Key key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Row(
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
color: Colors.orange,
border: Border.all(color: Colors.blueAccent)),
child: Text("My Awesome Border"),
)
],
)
],
);
}
}
There are several possibilities
1- Use MediaQuery.of(context).size.width,
Container(
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
color: Colors.orange,
border: Border.all(color: Colors.blue)),
child: Text("My Awesome Border"),
)
Here, make sure that your container has a parent that has context
2- Use double.infinity
Container(
width: double.infinity,
decoration: BoxDecoration(
color: Colors.orange,
border: Border.all(color: Colors.blue)),
child: Text("My Awesome Border"),
)
3- Use FractionallySizedBox widget
Creates a widget that sizes its child to a fraction of the total available space.
Example :
FractionallySizedBox(
widthFactor: 1.0, // between 0 and 1 // 1 for max
heightFactor: 1.0,
child:Container(color: Colors.red
,),
)
4- Use other widgets such as Expanded , Flexible and AspectRatio and more .
Output :
You can write:
Container(
width: double.infinity,
child: Text("My Awesome Border"),
)
I'm used to work with flutter for mobile devices and this kind of error usually happen when we don't have a Scaffold as the base widget. I mean, we can have a SafeArea that has a Scaffold as child, but I don't think we can use a Column as root. So try putting a Scaffold and setting the Column as Scaffold's body. Hope this answer helps you somehow!
By Using the LayoutBuilder a parent widget for your widget and set the constraint.maxWidth to your container to fill the Width.
LayoutBuilder(
builder: (context, constraint){
return Column(
children: <Widget>[
Row(
children: <Widget>[
Container(
width: constraint.maxWidth,
decoration:
BoxDecoration(border: Border.all(color: Colors.blueAccent)),
child: Text("My Awesome Border"),
)
],
),
],
);
},
),
Hope it will you to achieve your requirement.
You have missed wrapping the child widget inside the Scaffold Widget like below so that only its showing a red color text and yellow line
void main() {
runApp(MaterialApp(
title: "Practice",
home: CartScreen()
));
}
class CartScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Your Cart'),
),
body: LayoutBuilder(
builder: (context, constraint){
return Column(
children: <Widget>[
Row(
children: <Widget>[
Container(
width: constraint.maxWidth,
decoration:
BoxDecoration(border: Border.all(color: Colors.blueAccent)),
child: Text("My Awesome Border"),
)
],
),
],
);
},
),
);
}
}
Because you have used Column within MaterialPage without Scaffold or CupertinoScaffold. So if you wrap Your Column with Scaffold then you’ll see the Text’s yellow underlines removed and the text will be black.
And I see one other problem with your code, is it the wrong format for dart so it’s not readable so I mean it is not clean code.
Fully formatted code:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: buildBody(),
),
);
}
Widget buildBody(){
return Column(
children: <Widget>[
Row(
children: <Widget>[
Container(
decoration:
BoxDecoration(border: Border.all(color: Colors.blueAccent)),
child: Text("My Awesome Border"),
)
],
),
],
);
}
}
You are missing the Scaffold widget. Try using the scaffold widget before the column widget. It will fix the issue

Make widget Expanded size as min height in SingleChildScrollView Widget

Here is my code
child: Scaffold(
resizeToAvoidBottomPadding: false,
appBar: AppBar(),
drawer: MyDrawer(),
body: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
// direction: Axis.vertical,
children: [
Container(
height: 400,
child: Text('PageOne'),
),
IntrinsicHeight(
child: Expanded(
child: Container(
width: double.infinity,
color: Colors.grey,
child: Text(
'Hi',
textAlign: TextAlign.center,
),
),
),
),
],
),
),
),
I want this grey container in the screenshot fill the height as min height, I need it responsively with rotate the screen phone and for all phone screen size, it's only takes static height size when use SingleChildScrollView because unlimited height is available, i try to find way to make him take the remaining height of the screen as min height of container.
any ideas?
If you do know the height of the top part, you could use a mix of LayoutBuilder and ConstrainedBox like so:
import 'dart:math';
import 'package:flutter/material.dart';
main() {
runApp(MaterialApp(home: MyApp()));
}
class MyApp extends StatelessWidget {
final double headerHeight = 400;
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomPadding: false,
appBar: AppBar(),
body: LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
return SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
// direction: Axis.vertical,
children: [
Container(
color: Colors.red,
height: headerHeight,
child: Text('PageOne'),
),
ConstrainedBox(
constraints: new BoxConstraints(
minHeight: max(0, constraints.maxHeight - headerHeight),
),
child: Container(
width: double.infinity,
color: Colors.grey,
child: Text(
'Hi',
textAlign: TextAlign.center,
),
),
),
],
),
);
}
),
);
}
}
If you don't know the height of the top part, I would use key (or keys) to get their size and use the same widget tree as above.

ShrinkWrap Horizontal ListView inside Column with 'mainAxisSize: MainAxisSize.min' gives error : 'constraints.hasBoundedHeight': is not true

I am trying to display a horizontal ListView which height is given by its children inside a Column which height is also this of its children.
However, I'm getting the following error : 'constraints.hasBoundedHeight': is not true.
Here is a simple snippet to reproduce the error:
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
main() => runApp(MaterialApp(
home: Scaffold(
body: MyApp(),
),
));
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text('Vertical1'),
ListView(
scrollDirection: Axis.horizontal,
shrinkWrap: true,
children: <Widget>[
Container(
height: 100,
width: 100,
child: Text('Horizontal1'),
color: Colors.red,
),
],
),
Text('Vertical2')
],
);
}
}
As you see the children have a defined height so I don't get the issue.
Here is the expected output:
I know I can use a SingleChildScrollView but would just like to understand why it does not work with a ListView.
Just because your child has a size does not mean the ListView will take on that size.
You need to give a height to your ListView because by default its height is infinite.
You get this error because you can't place infinite height in a column,
so you give it a height with the widget Expanded if you want your list to take all the space available.
Here is an example:
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Column(
children: <Widget>[
Container(color: Colors.red, child: Text('Vertical1')),
ConstrainedBox(
constraints: BoxConstraints(
maxHeight: 100,
),
child: Container(
color: Colors.green,
child: ListView(
scrollDirection: Axis.horizontal,
shrinkWrap: true,
children: <Widget>[
Container(
height: 100,
width: 100,
child: Text('Horizontal1'),
),
],
),
),
),
Container(color: Colors.red, child: Text('Vertical2'))
],
),
),
);
}
}