Setting the height of stack layout widget - dart

I have a stack layout/widget inside which I have for ex. 10 Positioned child widgets. Each child widget is given a top position of +40 pixel ie. The first child's top position is 0, the 2nd child's top position is 40, the 3rd child's top position is 80 and so on. So I have to set the height of the stack layout = (height of the child + (10*40)). How can I do that?
Example code:
class _CardStackState extends State<CardStackWidget> {
List<Widget> cards;
double lastCardElevation = 1.0;
double lastCardYPosition = 0.0;
void buildCards(BuildContext context) {
this.cards = List();
widget.cardHeaderBodyMap.forEach((header, body) {
cards.add(_CardStackItem(
header: header,
body: body,
cardElevation: lastCardElevation++,
cardBackgroundColor: widget.cardBackgroundColor,
cardCornerRadius: widget.cardCornerRadius,
cardYPosition: lastCardYPosition,
screenHeight: MediaQuery.of(context).size.height,
));
lastCardYPosition += widget.cardHeaderHeight;
});
}
#override
Widget build(BuildContext context) {
buildCards(context);
return LayoutBuilder(
builder: (BuildContext context, BoxConstraints viewportConstraints) {
return SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: viewportConstraints.maxHeight,
),
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
(widget.headerWidget != null)
? widget.headerWidget
: Container(),
Container(
height: 1000,
margin: EdgeInsets.only(top: 4.0),
child: Stack(
children: cards,
),
),
],
),
),
);
},
);
}
}
See height of the container, I have set it to 1000, I have to set the actual height there. If I can able to determine the height of a card then I can do that.

Related

I want to make a listview within a column take up all available space

I am making a settings page and the layout is a container with a set height and then under it a listview however this listview needs a set height; so it works when I wrap it in a container and give it a height however it doesn't work if I wrap it in a expanded.
I have tried many things like putting it in a layout builder and giving the height as BoxConstraints.maxHeight and a lot of other tricks which should work but don't.
class Settings extends StatelessWidget {
Settings({#required this.userInfo, #required this.licenseInfo});
final userInfo;
final licenseInfo;
#override
Widget build(BuildContext context) {
double width = MediaQuery.of(context).size.width;
double height = MediaQuery.of(context).size.height;
return GestureDetector(
onTap: () {
FocusScope.of(context).requestFocus(new FocusNode());
SystemChannels.textInput.invokeMethod('TextInput.hide');
},
child: Scaffold(
resizeToAvoidBottomPadding: false,
backgroundColor: Colors.transparent,
appBar: AppBar(
elevation: 0.0,
backgroundColor: Color(0xFF77FDA7),
title: Text('Settings',
style: TextStyle(color: darkGrey, fontWeight: FontWeight.w600)),
),
body: Column(
children: <Widget>[
Stack(
children: <Widget>[
Container(
height: 91,
width: width,
decoration: BoxDecoration(gradient: greenGradient),
),
Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
SettingsProfile(
userInfo: this.userInfo,
licenseInfo: this.licenseInfo),
SizedBox(
height: 300,
child: SettingsList(),
),
],
),
],
),
],
)),
);
}
}
As you see there is a stack and another column however these are just parts of the UI and I need them. They do not have anything to do with me trying to fix this issue. PLEASE HELP as I need this listview to take up all available space in the column without overflowing.
I had a similar use-case and what I did on my app was wrap LayoutBuilder with Expanded. The LayoutBuilder fetches the dimensions of available screen space for the widget and it can be used to set the Widget's height.
Expanded(
child: LayoutBuilder(
builder: (BuildContext context,
BoxConstraints constraints) {
return Container(
height: constraints.maxHeight, // fetch height with Constraints
width: constraints.maxWidth,
child: ListView.builder(...),
);
}
),
)

Flutter - How to make PageView & ListView?

I'm trying to make a Carousel using PageView, PageController and ListView from this Horizontally scrollable cards with Snap effect in flutter. But it throwed this exception...
══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
I/flutter (17678): The following assertion was thrown during performResize():
I/flutter (17678): Horizontal viewport was given unbounded height.
I/flutter (17678): Viewports expand in the cross axis to fill their container and constrain their children to match
I/flutter (17678): their extent in the cross axis. In this case, a horizontal viewport was given an unlimited amount of
I/flutter (17678): vertical space in which to expand.
Can someone help me to fix it?
I want to add this Carousel inside of Stack-filled with background image, transform class, and fade transition.
#override
void initState() {
super.initState();
controller = PageController(
initialPage: 0,
keepPage: true,
);
#override
Widget build(BuildContext context) {
return AnimatedBuilder(
builder: (BuildContext context, Widget child) {
return Scaffold(
//BODY
body: ListView(children: <Widget>[
new Stack(
children: <Widget>[
new AspectRatio(...),
new Transform(...),
//THIS IS
new ListView.builder(
itemCount: 3,
scrollDirection: Axis.horizontal,
padding: EdgeInsets.symmetric(vertical: 16.0),
itemBuilder: (BuildContext context, int index) {
if (index % 3 == 0) {
return _buildCarousel(context, index ~/ 3);
} else {
return Divider();
}
},
),
}
}
}
Widget _buildCarousel(BuildContext context, int carouselIndex) {
return Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text('Carousel $carouselIndex'),
SizedBox(
// you may want to use an aspect ratio here for tablet support
height: 200.0,
child: PageView.builder(
// store this controller in a State to save the carousel scroll position
controller: PageController(viewportFraction: 0.8),
itemBuilder: (BuildContext context, int itemIndex) {
return _buildCarouselItem(context, carouselIndex, itemIndex);
},
),
)
],
);
Widget _buildCarouselItem(
BuildContext context, int carouselIndex, int itemIndex) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 4.0),
child: Container(
decoration: BoxDecoration(
color: Colors.grey,
borderRadius: BorderRadius.all(Radius.circular(4.0)),
),
),
);
This is the full code https://pastebin.com/xXRkaWuR
As you might have guessed from the error, basically it means since you haven't specified a finite height,ListView is getting infinite height.
Try using shrinkWrap: true inside your ListView.builder and ListView.
Or alternatively you can also try wrapping your ListViews in a Container or SizedBox of finite height.
Example-
Container(
height: 200.0,
child: ListView(
/*Remaining Code*/
),
)
You can try doing the same with ListView.builder

How to center flutter text with other widgets in row

I created a row with a BackButton and a TextWidget.
I want to center the text to the middle of the screen. Actually flutter centeres the text to the containers width, but the containers width isnt the same as the screen width, because there is the backbutton. How do i fix that?
Expanded getTitle() {
return new Expanded(
child: new Text("Einloggen", style: new TextStyle(fontSize: 18.0), textAlign: TextAlign.center)
);
}
BackButton getBackButton() {
return new BackButton(
);
}
Row getHeader() {
return new Row(
children: <Widget>[
getBackButton(),
getTitle()
],
);
}
#override
Widget build(BuildContext context) {
final double statusBarHeight = MediaQuery.of(context).padding.top;
return new Material(
child: new Container(
padding: new EdgeInsets.fromLTRB(0.0, statusBarHeight, 0.0, 0.0),
child: new Column(
children: <Widget>[
getHeader()
],
),
),
);
}
You can use the Row's mainAxisAlignment parameter to center align children of a row.
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
//children Widgets
]
);
Similarly, mainAxisAligment paramter can also be used to align Column's children. For more information check this out!
You can achieve the same UI using A Scaffold with AppBar
class mytab extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
centerTitle: true,
leading: new Icon(Icons.arrow_back),
title: new Text("Einloggen",
style: new TextStyle(fontSize: 18.0)),
),
);
}
}
To make the Title in the Center :
centerTitle: true
Based on your code
Widget getTitle() {
return const Text('Einloggen',
style: TextStyle(fontSize: 18.0), textAlign: TextAlign.center);
}
BackButton getBackButton() {
return const BackButton();
}
Row getHeader() {
return Row(
children: <Widget>[
Expanded(
child: getBackButton(),
),
const Spacer(),
getTitle(),
const Spacer(flex: 2)
],
);
}
#override
Widget build(BuildContext context) {
final double statusBarHeight = MediaQuery.of(context).padding.top;
return Material(
child: Container(
padding: EdgeInsets.fromLTRB(0.0, statusBarHeight, 0.0, 0.0),
child: Column(
children: <Widget>[getHeader()],
),
),
);
}
I don't know if it is still useful, but I found a solution thanks to widegtes: Container, Stack and Align.
Widget getTitle() {
return new Text("Einloggen", style: new TextStyle(fontSize: 18.0));
}
Widget getBackButton() {
return Container(
height: MediaQuery.of(context).size.height,
child: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: moveToLogin,
));
}
Widget getHeader() {
return Container(
height: 50.0,
// you must set a size to the Conteiener to make sure that the internal Align
// widens as much as possible.
child: new Stack(
// Stack places the objects in the upper left corner
children: <Widget>[
getBackButton(),
Align(alignment: Alignment.center, child: getTitle()),
],
),
);
}
final double statusBarHeight = MediaQuery.of(context).padding.top;
return new Container(
padding: new EdgeInsets.fromLTRB(0.0, statusBarHeight, 0.0, 0.0),
child: new Column(
children: <Widget>[getHeader()],
),
);
This is the result
Image

Flutter position fixed equivalent

Is it possible to fix an object in the screen that stays fixed regardless of scrolling?
Something similar to CSS position fixed.
You can absolutely position a child of a Stack widget using the Positioned widget.
The minimal example below places the red box above the list view, by placing the child in a Positioned widget after the ListView in the Stack's children.
List<String> todos = [...];
return new Stack(
children: <Widget>[
new ListView(
children: todos
.map((todo) => new ListTile(title: new Text(todo)))
.toList(),
),
new Positioned(
left: 30.0,
top: 30.0,
child: new Container(
width: 100.0,
height: 80.0,
decoration: new BoxDecoration(color: Colors.red),
child: new Text('hello'),
)
),
],
);
And here it is inside of a Scaffold body. If you add more items you'll find that the list scrolls without moving the red box.
You could use Positioned widget in a Stack Widget with AspectRatio widget and use the % distance like the below code.
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size; //get the screen size
List<String> todos = [...];
//the below if to get the aspect ratio of the screen i am using the app only in landscape
//if you need to use it in portrait you should add the sizes below
if((size.width / size.height) > 1.76){
aspect = 16 / 9;
}else if((size.width / size.height) < 1.77 && (size.width / size.height) >= 1.6){
aspect = 16 / 10;
}else{
aspect = 4 /3;
}
return new Scaffold(
body: new Center(
//layoutBuilder i can use the constraints to get the width and height of the screen
child: new LayoutBuilder(builder: (context, constraints) {
return new AspectRatio(
aspectRatio: aspect,
child: new Column(
children: <Widget>[
new ListView(
children: todos
.map((todo) => new ListTile(title: new Text(todo)))
.toList(),
),
new Positioned(
//constraints.biggest.height to get the height
// * .05 to put the position top: 5%
top: constraints.biggest.height * .05,
left: constraints.biggest.width * .30,
child: new Container(
width: 100.0,
height: 80.0,
decoration: new BoxDecoration(color: Colors.red),
child: new Text('hello'),
),
),
],
),
),
}),
),
);
}
}
Hope it will help you....
I prefer this solution:
Stack(
children: [
Column(
children: [
Container(...),
Container(...),
]
),
Positioned(top:50, child: Card(...))
]
)
Widget build(BuildContext context) {
return Column(
children: [
Container(
// covers 20% of total height
height: 200,
child: Stack(
children: [
Container(
height: 300,
decoration: BoxDecoration(
color: Colors.red,
),
),
Positioned(
bottom: 0,
left: 0,
width: 100,
height: 100,
child: Container(
height: 54,
decoration: BoxDecoration(
color: Colors.blue,
),
),
)
],
),
),
],
);
}
Adding a width and height to your Positioned widget will make it appear if you want to use top/left/bottom/right

Flutter scrollable body with horizontal list and grid as children

I'm having a hard time understanding how to best create a scrollable container for the body that holds inside children that by default are scrollable as well.
In this case the grid shouldn't scroll but it's the entire page that should scroll so you are able to see more of the elements inside the grid. So basically the whole content should move vertically with the addition of the ListView moving horizontally (but that works fine already)
I had it working but it was using a bunch of "silver" widget, and I'm hoping there's a better solution that works without using all those extra widgets.
Thanks
Here's my code so far:
class GenresAndMoodsPage extends AbstractPage {
#override
String getTitle() => 'Genres & Moods';
#override
int getPageBottomBarIndex() => BottomBarItems.Browse.index;
static const kListHeight = 150.0;
Widget _buildHorizontalList() => SizedBox(
height: kListHeight,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 20,
itemBuilder: (_, index) =>
CTile(heading: 'Hip Hop', subheading: '623 Beats'),
),
);
Widget _buildGrid() => GridView.count(
crossAxisCount: 2,
crossAxisSpacing: LayoutSpacing.sm,
mainAxisSpacing: LayoutSpacing.sm,
children: List.generate(10, (index) {
return CTile(
padding: false,
heading: 'Kevin Gates Type Beat',
subheading: '623 FOLLOWERS',
width: double.infinity,
);
}),
);
#override
Widget buildBody(_) {
return ListView(children: [
CSectionHeading('Popular Genres & Moods'),
_buildHorizontalList(),
CSectionHeading('All Genres & Moods'),
_buildGrid(),
]);
}
}
The result should be something like this
Create List with Horizontal Scroll direction and called it as a child for Vertical Scroll direction.
body: new ListView.builder(itemBuilder: (context, index){
return new HorizList();
})
class HorizList extends StatelessWidget{
#override
Widget build(BuildContext context) {
return new Container(
height: 100.0,
child: new ListView.builder(itemBuilder: (context, index){
return new Card(child: new Container(width: 80.0,
child: new Text('Hello'),alignment: Alignment.center,));
}, scrollDirection: Axis.horizontal,),
);
}
}
As we want Popular Genres & Moods section also to scroll, we should not using nestedScroll. In above example GridView is nested inside `ListView. Because of which when we scroll, only the GridView will scroll.
I used Only one ListView to achieve the similar screen.
Number of children = (AllGenresAndMoodsCount/2) + 1
divide by 2 as we are having 2 elements per row
+1 for the first element which is horizontal scroll view.
Please refer the code:
import 'package:flutter/material.dart';
void main() {
runApp(new Home());
}
class Home extends StatelessWidget {
#override
Widget build(BuildContext context) {
var image = new Image.network("http://www.gstatic.com/webp/gallery/1.jpg");
var container = new Container(
child: image,
padding: EdgeInsets.only(left: 5.0, right: 5.0, top: 5.0, bottom: 5.0),
width: 200.0,
height: 200.0,
);
return MaterialApp(
title: "Scroller",
home: Scaffold(
body: Center(
child: new ListView.builder(
itemBuilder: (context, index) {
if (index == 0) { //first row is horizontal scroll
var singleChildScrollView = SingleChildScrollView(
child: Row(
children: <Widget>[
container,
container,
container,
],
),
scrollDirection: Axis.horizontal);
return singleChildScrollView;
} else {
return new Row(
children: <Widget>[container, container],
);
}
},
itemCount: 10, // 9 rows of AllGenresAndMoods + 1 row of PopularGenresAndMoods
)),
),
);
}
}

Resources