How to set dynamic height for Container Widget in flutter? - flutter

I have text widget inside of container and if text is more than 4 lines this is overflowing to bottom of container. How can I set dynamic height for this container that will depends of text lines and avoid bottom overflow ? At the moment container have fixed value but if I remove this value it will disappear.
home component
Widget build(BuildContext context) {
return Container (
child: SliverToBoxAdapter(
child: Container(
height: 180,
margin: EdgeInsets.only(top: 10),
child: CustomeInfoWidget(
infoData: _infoDataList,
),
),
),
)
}
CustomeInfoWidget
Widget build(BuildContext context) {
final double _width = MediaQuery.of(context).size.width;
return Container(
margin: EdgeInsets.only(top: 15, left: 15, right: 15),
child: Stack(
children: [
PageView.builder(
itemCount: widget._infoDataList.length,
controller: _pageController,
itemBuilder: (BuildContext context, int index) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: _width - 10,
child: Padding(
padding: const EdgeInsets.only(bottom: 10),
child: Text(widget._infoDataList[index].title,
textAlign: TextAlign.left,
),
Container(
child: Text(
widget._infoDataList[index].content,
),
)
],
);
},
),
],
),
);
}

wrap your container with Singlechildscrollview or set overflow for your Text widget Flutter - Wrap text on overflow, like insert ellipsis or fade

On your home component, you are fixing the height of CustomeInfoWidget. You can remove this.
SliverToBoxAdapter(
child: Container(
// height: 180,// remove this
margin: EdgeInsets.only(top: 10),
child: CustomeInfoWidget(
You can use SliverFillRemaining for PageView.
SliverFillRemaining(
child: PageView.builder(
Or you can wrap your text container with Singlechildscrollview for inner scroll.
You can also calculate the text height and provide it.
How can I get the size of the Text widget in Flutter

Related

How to fix Flutter web release showing grey screen but no debug error

I have created a flutter webapp but I have a screen that shows a grey page not sure why, I think its something to do with the listview since all pages with the listview have the same problem. Can you take a look at the code below to figure out the problem?
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Scaffold(
endDrawer: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 300),
child: const SideMenu()),
body: SingleChildScrollView(
child: SafeArea(
child: Container(
width: size.width,
constraints: BoxConstraints(minHeight: size.height),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
const NavBar(),
This is where the grey screen start to appears
const BrowseScreenBody(),
const Footer(),
]),
),
),
),
);
}
}
class BrowseScreenBody extends StatelessWidget {
const BrowseScreenBody({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
final events = Event.events.toList();
return Container(
margin: const EdgeInsets.symmetric(vertical: 20, horizontal: 40),
child: Expanded(
child: Padding(
padding: ...,
child: Column(
children: <Widget>[
RichText(
text: TextSpan(
children: [
...
],
),
),
//Events Lists
SizedBox(
height: size.height * 0.65,width: size.width,
child: ListView.builder(
shrinkWrap: true,
itemCount: events.length,
itemBuilder: (context, index) {
final event = events[index];
return Card(
child: Container(
decoration: BoxDecoration(
color: Colors.white),
child: Padding(
padding: ...
child: Column(
children: [
Row(
children: [
Container(
height: size.height * 0.25,
width: size. Width * 0.4,
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(...))),
),
Row(
children: [
Column(
children: [...
],
),
],
)
],
)
],
),
),
),
);
}),
),
],
),
),
));
}
}
Everything works well on debug mode, but when hosted to github pages I can't seem to get the widgets shown.
The problem is that you are using an Expanded as child of a Container. Expanded can only be a child of a Flex widget like Row or Column. But it's very likely that you actually do get errors in debug mode as well in your console. Because when I tried your code (slightly modified to make it runnable) it did give an error. Something like
======== Exception caught by widgets library =======================================================
The following assertion was thrown while applying parent data.:
Incorrect use of ParentDataWidget.
The ParentDataWidget Expanded(flex: 1) wants to apply ParentData of type FlexParentData to a RenderObject, which has been set up to accept ParentData of incompatible type BoxParentData.
Usually, this means that the Expanded widget has the wrong ancestor RenderObjectWidget. Typically, Expanded widgets are placed directly inside Flex widgets.
The offending Expanded is currently placed inside a Padding widget.

Horizontal scrolling ListView.builder inside SingleChildScrollView - wrap content height

My layout is a Form widget with some controls:
Column(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Form(
key: widget.addEventFormKey,
onChanged: () {},
child: Expanded(
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(CustomResources.strings["add_event_category_label"], style: TextStyle(fontWeight: FontWeight.bold)),
/*some other widgets*/
Visibility(
child: Container(
height: 200.0,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: _attachments?.length,
itemBuilder: (context, index) {
return Stack(
children: [
Container(
margin: EdgeInsets.fromLTRB(0, 0, 5, 0),
child: Stack(
children: [
ClipRRect(
child: Image.file(File(_attachments[index]), cacheWidth: 200),
borderRadius: BorderRadius.circular(8.0),
),
],
),
),
IconButton(
onPressed: () {
File(_attachments[index]).delete();
setState(() => _attachments.remove(_attachments[index]));
},
icon: Icon(FontAwesomeIcons.trash, color: Colors.white, size: 20),
padding: EdgeInsets.only(top: 4, left: 4),
constraints: BoxConstraints(),
),
],
);
},
),
),
visible: _attachments.length > 0,
),
Visibility(child: Padding(padding: EdgeInsets.fromLTRB(0, 18, 0, 0)),visible: _attachments.length > 0),
SizedBox(
child: RaisedButton(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(24.0)),
onPressed: _attachments.length < 3 ? () => _pickImage() : null,
padding: EdgeInsets.all(12.0),
color: Colors.blue,
child: Text(CustomResources.strings["add_event_add_photo_button_label"], style: TextStyle(color: Colors.white))),
width: double.infinity,
),
],
),
),
),
),
],
);
Problematic part is ListView.builder to display horizontally scrolled list of images. As you can see, picture will always get fixed width (200) and unknown height, because height depends from image aspect ratio. ListView.builder is wrapped with Container, so now it has constant height 200.
I want to force my ListView.builder to expand to child image height (it's single row ListView scrolled horizontally), image width always 200 and other widgets should be placed below it without any remaining space. With current approach, if image height is < 200, there will be remaining space left below image list. If image height is >200, image will be scaled (width/height).
I tried to wrap list view with Expanded widget instead Container, but it throws exception:
RenderFlex children have non-zero flex but incoming height constraints
are unbounded.
It says I still need to provide height, which I don't want to. How to solve this?
I think that's not possible with ListView.builder, because its height with dynamic items is not known while building widgets tree. Instead, my thumbnail widgets mus be built upfront, and added to Row after they have been built and wrap row with SingleChildScrollView to make it scrollable. So, my thumbnails list ready to place to my Form:
class AttachmentsListWidget extends StatelessWidget {
const AttachmentsListWidget({
Key key,
#required this.items,
#required this.onAttachmentDeleted,
}) : super(key: key);
final List<String> items;
final Function(String) onAttachmentDeleted;
#override
Widget build(BuildContext context) {
var _thumbnailsScrollController = ScrollController();
final thumbnails = <Widget>[];
Widget thumbnailsWidget;
if (items.length > 0) {
for (int i = 0; i < items.length; i++) {
thumbnails.add(
AttachmentWidget(
attachment: items[i],
onDeleteClicked: (String attachment) => onAttachmentDeleted(attachment),
),
);
}
thumbnailsWidget = Container(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Scrollbar(
isAlwaysShown: true,
controller: _thumbnailsScrollController,
child: SingleChildScrollView(
controller: _thumbnailsScrollController,
scrollDirection: Axis.horizontal,
child: Row(
children: thumbnails,
crossAxisAlignment: CrossAxisAlignment.start,
),
),
),
],
),
);
} else {
thumbnailsWidget = Container();
}
return thumbnailsWidget;
}
}
(also, always visible scrollbar added).
If you got RenderFlex children have non-zero flex but incoming height constraints are unbounded. try below code hope its help to you. add your Column inside Expanded() Widget and remove SingleChildScrollView() in your code
Expanded(
child: Column(
children:[
//Your Widgets
],
),
),

Why is expanded container not visible within list view?

I have a widget that displays a 100x100 image and a blue container next to it which fills the rest of the Row.
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
Scaffold.of(context).showSnackBar(SnackBar(content: Text(title)));
},
child: Container(
padding: EdgeInsets.all(24),
child: Row(
children: [
SizedBox(
child: Image.asset("assets/img_small.png"),
width: 100,
height: 100),
Expanded(
child: Container(margin: EdgeInsets.only(left: 12), color: Colors.blue)
)
],
),
));
}
This works fine but as soon as I use it within a list view, the blue container is not visible:
#override
Widget build(BuildContext context) {
return ListView.separated(
itemCount: list.length,
separatorBuilder: (context, index) =>
Divider(color: Colors.grey, thickness: 2, height: 0, indent: 8),
itemBuilder: (context, position) {
return BlueBoxWidget(title: list[position]);
});
}
What am I doing wrong?
I am mostly interested why inside a listview the blue container doesn't try to expand its height as much as possible.
The blue Container is there, but with 0 height.
Try adding some height, like this, to get the container visible
Expanded(
Container(
height: 50,
margin: EdgeInsets.only(left: 12),
color: Colors.blue
),
)
try to remove the Expanded widget that wrapped the Container it maybe work.

ListView does not work as a child of Column or Row

I`m new in flutter framework and I want to use CustomLists.
My (body:) I wants to add a listviewBuilder into a Column but I give an empty page. if I use only listView in body part every things is fine.
Here is my Widget:
Widget _buildListView() {
return ListView.builder(itemBuilder: (BuildContext context, int index) {
return Dismissible(
key: Key('ke'),
onDismissed: (DismissDirection direction) {
if (direction == DismissDirection.endToStart) {
print('Swiped end to start');
} else if (direction == DismissDirection.startToEnd) {
print('Swiped start to end');
} else {
print('Other swiping');
}
},
background: Container(
color: Colors.red,
),
child: Container(
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Expanded(
child: Column(children: <Widget>[
Row(
children: <Widget>[
Container(
margin: EdgeInsets.symmetric(
horizontal: 8.0, vertical: 2.0),
padding: EdgeInsets.all(4.0),
color: Colors.red,
child: Text('12'),
),
SizedBox(
width: 8.0,
),
Text('135'),
],
)
]),
),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Row(
children: <Widget>[
Container(
color: Colors.green,
width: 15,
height: 10,
),
SizedBox(
width: 5,
),
Text('120'),
SizedBox(
width: 5,
),
Container(
color: Colors.yellow,
width: 15,
height: 10,
),
],
)
]),
),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Text('30'),
])),
],
),
Divider()
],
)),
);
},itemCount: 10,);
}
I get this errors:
The following assertion was thrown during performResize():
I/flutter (14466): Vertical viewport was given unbounded height.
I/flutter (14466): Viewports expand in the scrolling direction to fill their container.In this case, a vertical
I/flutter (14466): viewport was given an unlimited amount of vertical space in which to expand. This situation
I/flutter (14466): typically happens when a scrollable widget is nested inside another scrollable widget.
I/flutter (14466): If this widget is always nested in a scrollable widget there is no need to use a viewport because
I/flutter (14466): there will always be enough vertical space for the children. In this case, consider using a Column
I/flutter (14466): instead. Otherwise, consider using the "shrinkWrap" property (or a ShrinkWrappingViewport) to size
I/flutter (14466): the height of the viewport to the sum of the heights of its children.
add shrinkWrap property true for listview.
ListView.builder(
shrinkWrap:true,
itemBuilder: (BuildContext context, int index) {
return Container();
});
you have to wrap your ListView in a container that has the specified width and height values.
for example, wrap the ListView in the Container with height and with values or wrap it to an Expanded widget to fill the entire space its parent.
Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: ListView.builder() // your list view builder widget
)
or
Expanded(
child: ListView.builder() // your list view builder widget
)
note that you should use the Expanded widget inside a flex widget that has specified the width and height values. like Column, Row , ...
Also, you should set the shrinkWrap value to true when using ListView inside another ListView widget.

how to prevent horizontal ListView items from stretching

I have a horizontal ListView inside a Column.
My ListView is rendering 100 x 100 items that i want to animate their height to 200 later.
I am wrapping my ListView inside a Container that has a height of 200 other wise i get errors and the code will not run
The problem now is that the list items are stretching their height to 200.
Is there a way to prevent that behavior, i tried alignment but it didn't work.
Here's the code so far
Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
height: 200,
child: ListView(
scrollDirection: Axis.horizontal,
children: <Widget>[
CCard(),
CCard(),
CCard(),
CCard(),
CCard(),
],
),
),
],
));
And the List items
class CCard extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.symmetric(horizontal: 8.0),
height: 100,
width: 100,
color: Colors.red[200],
);
}
}
Try wrapping your Container inside Align or Center, like this :
class CCard extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Center(
child: Container(
margin: EdgeInsets.symmetric(horizontal: 8.0),
height: 100,
width: 100,
color: Colors.red[200],
),
);
}
}
More info: https://docs.flutter.io/flutter/widgets/Container-class.html