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.
Related
I am trying to achieve scroll in Flutter Web where I have few containers which are stacked and I use SingleChildScrollView to scroll the widget. However, when I scroll the first container everything working fine but the second one which is a child of the second container responds to the scroll without completing the initial one. And also is there a way to make a sticky header for the second container. How can I make the 3rd container(orange) to scroll after the 2nd(blue) one is finished scrolling? Here is what I am trying to achieve:
https://yobithemes.com/demo/html/freda/dark-video-index.html
And here what I got so far:
class MainScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: <Widget>[
IntroScreen(),
SingleChildScrollView(
child: Container(
child: Column(
children: <Widget>[
SizedBox(
height: MediaQuery.of(context).size.height - 100,
),
Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
color: Colors.blue,
child: SingleChildScrollView(
child: Column(
children: [
SizedBox(
height: MediaQuery.of(context).size.height,
),
Container(
padding: EdgeInsets.only(top: 100),
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
color: Colors.orange,
),
],
),
),
),
],
),
),
),
],
),
);
}
}
You can achieve it by using sliver.
SliverToBoxAdapter fill the transparent area with screen height - app bar height.
SliverAppBar: make it sticky by setting floating and pin to true
class MainScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: <Widget>[
IntroScreen(),
CustomScrollView(
slivers: [
SliverToBoxAdapter(
child: Container(
height: MediaQuery.of(context).size.height - 50,
),
),
SliverAppBar(
// toolbarHeight: 50,
floating: true,
pinned: true,
title: Container(
child: Center(child: Text('Header')),
),
),
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) => Container(
height: MediaQuery.of(context).size.height-50,
color: Colors.primaries[index % Colors.primaries.length],
),
),
),
],
),
],
),
);
}
}
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!'),
),
),
],
),
)
],
),
When used inside ListView, Card's width can be controlled with a SizedBox, but height stays unbounded. I would like to know how to limit it.
Widget buildCard(String text) {
return SizedBox(
height: 220.0, // this does not work
width: 180.0, // this works
child: Card(
child: Column(
children: [
ListTile(
title: Text('Title: $text'),
subtitle: Text('Subtitle: $text'),
),
],
),
),
);
}
Widget build(BuildContext context) {
return MaterialApp(
// ...
home: Scaffold(
// ...
body: ListView(
children: [
buildCard('one'),
buildCard('two'),
buildCard('three'),
buildCard('four'),
buildCard('five'),
],
scrollDirection: Axis.horizontal,
),
),
);
}
A demo is available at DartPad.
Give height to ListView only
SizedBox(
height: 220,
child: ListView(
//....
I'm having an issue trying to make one of my containers stretch to max screen height,
home: Scaffold(
backgroundColor: Colors.teal,
body: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
height: double.infinity,
width: 100,
color: Colors.red,
)
],
),
),
),
I thought by making the height value infinity it would stretch the red container across the entirety of the safe area.
Although the container is invisible unless I put a value in height.
You should use an Expanded widget.
According to the official documentation, An Expanded widget is a widget that expands a child of a Row, Column, or Flex so that the child fills the available space.
Read more about the Expanded widget here: Expanded Widget
class Test extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.teal,
body: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Container(
width: 100,
color: Colors.red,
),
)
],
),
),
);
}
}
OUTPUT
Wrapping the container to Expanded will make its size max like this :
home: Scaffold(
backgroundColor: Colors.teal,
body: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Container(
width: 100,
color: Colors.red,
)
)
],
),
),
),
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'))
],
),
),
);
}
}