Any alternative to Expanded widgets using with ListView.builder - flutter

I need to design a screen that shows a different widget (selectedWidget) depending on which button is selected. Problem is that the content is dynamic and I have to use ListView.builder for all the APIs. And ListView.builder only works when the Row containing listview is wrapped in Expanded widget. I want to have two buttons just below my ListView, which I'm not able to achieve due to the Expanded widget which covers up the entire Column in which the ListView is present.
The code gives the basic structure which I've been using. selectedWidget is the ListView.builder widget which will be selected according to the FlatButton selected. Also the Column which contains the selectedWidget has dynamic height. It should adjust according to the size of the listview, so I cannot define a fixed height or even a maxHeight. I can only give minHeight here. And the two buttons below my ListView should be right below my ListView and take the width of the Column with flex 3.
I've also tried disabling the scroll for ListView and using SingleChildScrollView, but then my two buttons below the ListView also start scrolling, which I don't want. I need them to be static on the screen and only the ListView should scroll.
I need a solution for the above problem. I need a workaround for this Expanded widget which doesn't let me align my buttons right below my listview and gives white space. Please share if there is any alternative to ListView.builder because I don't think I can use ListView.builder without the Expanded widget. I've tried every possible structure with ListView and Expanded widget.
class MyScreen extends StatefulWidget {
#override
_MyScreenState createState() => _MyScreenState();
}
class _MyScreenState extends State<MyScreen> {
#override
Widget build(BuildContext context) {
return Column(
children:[
Expanded(
child: Row(
Expanded(flex: 2,
child: Column(
children: [
FlatButton(),
FlatButton(),
FlatButton(),
FlatButton(),
]
)
),
Expanded(flex: 3,
child: Column(
children: [
Expanded(selectedWidget),
Row(children: [FlatButton(), FlatButton()], )
]
)
),
)
)
],);
}
}

Maybe you can use Flexible and set shrinkWrap: true, inside ListView. The following 2 buttons may not need Expand widget after that.
child: Column(
children: [
Flexible(
child: ListView.builder(
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) => Text(index.toString()),
itemCount: 6,
),
),
Row(
... // 2 Buttons

Related

How can I place different elements in a List in Flutter?

As in the image; How can I create a list structure where the list items can be selected, the user can enter data with the textField and I can use the Text() Widget?
You can use the ListView widget.
It accepts a list of widgets as it's children, so you are not limited to ListTile.
Code should look something like this:
ListView(
padding: const EdgeInsets.all(8),
children: <Widget>[
Container(), //Your widget here
Container(), //Your widget here,
Container(), //Your widget here
...
],
)

ListView Builder vs SingleChildScrollView + Row combo

I want to make a responsive UI in my app. In my home page, I have ScrollView->Column->childrens structure.
When I want to use horizontal Listview.builder in my column, it throws me error because height is unbounded. I fix it with wrapping my listview builder with container and I give this container a height value. But I dont want to give this height hardcoded,
I want to make my container height to its own child's height. I searched it and found a solution like ScrollView->Row->list.generate instead of ListView.Builder. But is it okay to make it like this? Does it cause performance problems or is it a bad practice?
My list isn't big. It has max 20 elements
For example this throwing error:
#override Widget build(BuildContext context) {
return Container(
color: Colors.red,
child: SingleChildScrollView(
child: Column(
children: [
ListView.builder(
itemCount: 5,
physics: NeverScrollableScrollPhysics(),
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemBuilder: (context, index) {
return Container(
width: 200,
height: 200,
);
},
)
],
)),
); }
But this does not throw an error
#override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Column(
children: [
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: List.generate(
5,
(index) => Container(
width: 200,
height: 200,
color: Colors.red,
)),
),
),
],
));
}
To clarify for everyone:
ListViews generate their children "lazily" - meaning they won't be drawn until they have been shown on screen. This means, of course, that they do not know the height of their items.
For example, if the ListViews children have heights similar to this list:
ooooOooo
But only this part was shown on the screen:
oooo | Oooo
And the ListView set it's height to fit "o" then it wouldn't be able to fit "O" when it eventually came on screen.
On the other hand, Rows do draw all of their children on spawn, meaning that, while they do know the size for all their widgets, they can become very slow quickly.
I would not suggest using images inside rows with 2-digit+ children, as they can be laggy not only on their initial draw, but also while the user does other things in the page containing said row - things such as scrolling up/down the page.
While testing I found that a row with just 30 children of the same stack (a small AssetImage on top of an IconImage) would lag the entire page when just scrolling up/down - not even scrolling along the row itself.
My recommended solution for you Ahmet, even though you don't want to hard-code your ListView's height, is to settle and set your ListView's height using:
MediaQuery.of(context).size.height * (percentage of screen's height you'd like for the ListView to take).

Card and ListView on single screen

I have a dropdown box and a listview below it on a screen.
On selection of a item in dropdownbox, the list view gets populated with multiple cards. As such the logic is working, but somehow having issues with the scroll configuration.
I have the main parent widget like this:
Widget build(BuildContext context) {
return Column(
children: <Widget>[locationDropdown(), showPackages(plansLoading)],
);
}
The locationDropDown() function returns a card widget with dropdown in it.
showPackages(plansLoading) returns a ListView widget whose code is like
return ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
return Card(
color: Colors.transparent,
child: Column(
children: <Widget>[
///...
],
),
);
)
Requirement is to keep the card in the loationDropdown() widget fixed at its place and the cards generated in showPackages's listview be scrolled.
This is the output I am getting, I am unable to scroll.
This functionality is not working. Where am I going wrong?
you can used SafeArea Widget or use Expanded widget before Listview.
ex.
Column (
children: <Widget>[
new TextField(
decoration: new InputDecoration(
labelText: "Search something"
),
Expanded(
ListView(),
),
]
)

How to iterate over list to incorporate it in a wrap widget?

I am trying to restrict the items(Containers) in the Row to 8 and if there are more items, they should be wrapped. I have a list of Containers but I can not use listView as children of Wrap since listView scrolls. Is there any way to get this layout fixed?
I have tried using for loop but as it hits return for the first time, it gets out of loop.
I have tried gridView instead of wrap but it doesn't give me the result as gridView is scrollable.
Expanded(
flex: 4,
child: Wrap(
direction: Axis.horizontal,
spacing: 0.5,
runSpacing: 0.5,
crossAxisAlignment: WrapCrossAlignment.center,
children: <Widget>[
// I want something that works like following line
//Container(child: kids1)
//currently I can get results with following code
kids1[1],
kids1[2],
kids1[3], kids1[4], kids1[5], kids1[6],
kids1[7], kids1[8], kids1[9], kids1[10],
kids1[11]
],
),
),
kids is a list of Containers
Why don't you create the list of children before the return of the build function :
#override
Widget build(BuildContext context) {
List<Widget> children = List.generate(myContainerList.length, (e) => myContainerList[e]);
return Wrap(
children: children,
);
}

Flutter - Scrollable List of Widgets

I have a screen that displays a list of widgets, something like this:
Column(
children: listW,
),
The listW object is of type List<Widget>. The first index contains a ListTitle and all others are of type Card. The number of cards are added dynamically. Now the problem is that when the list has lets say 10 Card objects, it is hidden below the screen. I need some sort of a ScrollableView to contain my list. How can I do that since SingleChildScrollableView can bear only one widget. How can I deal with this issue?
Try changing you code to this
ListView(children: listW,)
You can use a ListView() for this.
ListView(
children: <Widget>[
//Your widgets
]
)
Keep in mind, that a list view renders all the items currently in the list, which means huge lists will cause performance issues. You can get around this using a ListView.builder, since this creates items as they are scrolled on the screen.
class FruitList extends StatelessWidget{
final List<String> fruits = [ "Apple", "Banana", "Pear", "Orange", "Kiwi" ];
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
padding: EdgeInsets.all(5),
child: ListView.builder(
itemBuilder: _buildFruitItem,
itemCount: fruits.length,
)
)
);
}
Widget _buildFruitItem( BuildContext context, int index ){
return Card(
child: Text( fruits[index] ),
);
}
}
You can checkout more documentation on this here: https://flutter.io/docs/cookbook/lists/long-lists