ListView inside a Row with dynamic width - flutter

I want to create a ListView and a Button to add items to the ListView.
Row(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Expanded(
child: ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) {
Conversation conversation = teamMembers[index];
return SizedBox(
width: 42,
height: 42,
child: Avatar(
name: member.name,
profileUrl: member.profileUrl,
radius: 38,
),
);
},
itemCount: teamMembers.length,
),
),
InkWell(
onTap: () {
_showSheet();
},
child: Container(
width: 42,
height: 42,
decoration: new BoxDecoration(
color: Color(0xfff2f2f2),
borderRadius: BorderRadius.circular(28)),
child: Icon(Icons.add),
),
),
],
)
I'm getting the results as below for lesser number of items and more number of items. How can I make the + button closer to the ListView even if the list length is less.

List<Widget> _buttons = [];
Wrap(
spacing: 12.0, // horiz
runSpacing: 12.0, // vert
crossAxisAlignment: WrapCrossAlignment.start,
alignment: WrapAlignment.start,
children: _buttons,
),

The solution to this issue is replacing the Expanded widget with Flexible widget.
Expanded actually is just a shorthand for Flexible. Flexible takes only the needed space, and Expanded takes all available space, respecting the flex factor.
Flexible with fit: FlexFit.loose which is the default one solves the problem. If the fit is FlexFit.loose, the child can be at most as large as the available space (but is allowed to be smaller)
So,
Row(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Flexible(
child: ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) {
Conversation conversation = teamMembers[index];
return SizedBox(
width: 42,
height: 42,
child: Avatar(
name: member.name,
profileUrl: member.profileUrl,
radius: 38,
),
);
},
itemCount: teamMembers.length,
),
),
InkWell(
onTap: () {
_showSheet();
},
child: Container(
width: 42,
height: 42,
decoration: new BoxDecoration(
color: Color(0xfff2f2f2),
borderRadius: BorderRadius.circular(28)),
child: Icon(Icons.add),
),
),
],
)
is the solution.

Related

Shrinkwrap for table-like listview not working?

I am trying to make a table-like listview (Im not using datatable or table because I want animations for adding items)
here is what I have come up with:
Column(mainAxisSize: MainAxisSize.min, children: [
LimitedBox(
maxHeight: 200.0,
child: ListView(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
children: [
LimitedBox(
maxWidth: 1000,
child: ListView.builder(
shrinkWrap: true,
itemCount: 3,
itemBuilder: (context, index) {
return Container(
color: Colors.red,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text('aaaaaaaaa$index'),
SizedBox(
width: 10,
),
Text('aaaaaaaaa$index'),
SizedBox(
width: 10,
),
Text('aaaaaaaaa$index'),
SizedBox(
width: 10,
),
Text('aaaaaaaaa$index'),
SizedBox(
width: 10,
),
Text('aaaaaaaaa$index'),
SizedBox(
width: 10,
),
Text('aaaaaaaaa$index'),
SizedBox(
width: 10,
),
Text('aaaaaaaaa$index'),
],
));
}),
)
],
),
)
]);
it came out like this:
you notice theres extra space at the bottom and the right side, I tried using shrinkwrap to get rid of that but clearly it didnt work. Does anyone know a solution to those?

it's possible to make listview in expand and fill parent without overflow?

it's possible to make listview in expand and fill the container without overflow the container, and shrink when listview is short of content without declare manual min or max height?
Code
Flexible(
fit: FlexFit.loose,
child: Container(
padding: EdgeInsets.symmetric(vertical: 20, horizontal: 10),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(kBoxRadius),
boxShadow: [kBoxShadow]),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
DText(
"Aug 2021",
size: 12,
weight: FontWeight.bold,
),
SizedBox(height: 10),
Row(
children: dates,
),
SizedBox(height: 15),
Container(
height: 1,
color: Color(0xFFE7E7E7),
),
Container(
constraints:
BoxConstraints(minHeight: 0, maxHeight: 600),
child: ListView.separated(
shrinkWrap: true,
itemBuilder: (context, index) {
return DText("Asd");
},
separatorBuilder: (_, __) {
return SizedBox(height: 10);
},
itemCount: 20,
),
)
],
),
),
)
Expectation
when the content is big
because i set manually max height.
Yes, it is possible using shrinkWrap: true. The code will be something like below,
class App extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(),
body: Center(
child: Container(
color: Colors.red,
child: ListView(
shrinkWrap: true,
children: <Widget>[
ListTile(title: Text('Apple')),
ListTile(title: Text('Orange')),
ListTile(title: Text('Banana')),
],
),
),
),
),
);
}
}

Not able to nest list in ExpansionTileCard in flutter

I am trying to nest listview.builder in ExpansionTileCard but not able to do so I am getting this error
ERROR
The following assertion was thrown during performResize():
Vertical viewport was given unbounded height.
CODE
ExpansionTileCard(
leading: GestureDetector(
onTap: (){
var firstdata = jsonResponse['content'];
code = firstdata[index]['code'];
},
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Image.asset('images/appicon.png', width: 50, height: 50)),
),
title: GestureDetector(
onTap: (){
var firstdata = jsonResponse['content'];
code = firstdata[index]['code'];
name = firstdata[index]['name'];
Navigator.push(context, MaterialPageRoute(builder: (context) =>PageViewClass(companycode: code,userid: widget.userid,)));
},
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(firstdata[index]['name'] ?? 'NULL PASSED'),
],
),
),
children: <Widget>[
Divider(
thickness: 1.0,
height: 1.0,
),
Align(
alignment: Alignment.center,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 8.0,
),
child:ListView.builder(
itemCount: list1.length,
itemBuilder: (BuildContext ctx, int index){
return Text(list1[index]['name']);
}
)
),
),
],
);
TheExpansionTileCard is already used in a parent Listview.builder .
Please guide me to resolve this issue
In Listview.builder you can try to keep shrinkWrap: true,
and in Column Widget, you can keep mainAxisSize = MainAxisSize.min,
A combination of this both should do the trick.

How do i return expanded widgets from ListView.builder?

I have tried to return a list of widgets in horizontal direction, i want to expand widgets width dynamically. how can i achieve this. (Note: ListView.builder placed inside column)
ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemCount: widget.playType.length,
itemBuilder: (BuildContext context, int index) {
return Flex(
direction: Axis.horizontal,
children: <Widget>[
Flexible(
child: InkWell(
onTap: () {},
child: Container(
padding: EdgeInsets.only(left: 10, right: 10),
color: colorSubMenuBg,
height: 45,
child: Align(
alignment: Alignment.center,
child: Text(
widget.playType[index],
style: CustomTextStyle.listTile4(context),
),
),
),
),
),
],
);
});
Expected output should be like this highlighted part:
Wrap Container( height: 70)in your ListViewBuilder()
like this
Container(
height: 70,
child: ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemCount: widget.playType.length,
itemBuilder: (BuildContext context, int index) {
return Flex(
direction: Axis.horizontal,
children: <Widget>[
Flexible(
child: InkWell(
onTap: () {},
child: Container(
padding: EdgeInsets.only(left: 10, right: 10),
color: colorSubMenuBg,
height: 45,
child: Align(
alignment: Alignment.center,
child: Text(
widget.playType[index],
style: CustomTextStyle.listTile4(context),
),
),
),
),
),
],
);
}),
);```
Actual working code, i removed flex from ListView.builder and added width for ListItems and ListView.
var buttonListWidth = MediaQuery.of(context).size.width;
Container(
height: 45,
width: buttonListWidth,
child: ListView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemCount: widget.playType.length,
itemBuilder: (BuildContext context, int index) {
return InkWell(
onTap: () {
setState(() {});
},
child: Container(
color: colorSubMenuBg,
height: 45,
width: buttonListWidth / widget.playType.length,
child: Align(
alignment: Alignment.center,
child: Text(
widget.playType[index],
style: CustomTextStyle.listTile4(context),
),
),
),
);
}))
Try adding a Row over the ListView.builder and add mainAxisSize: MainAxisSize.min, property to that Row.
ItemExtent property of ListView.builder
itemExtent: MediaQuery.of(context).size.height / LENGHT,

How to make a bottom sheet with height follow the amount of item of JSON

BottomSheet in Flutter so that the height follows the number of items (data from JSON) is that what? Because I made the height not follow the amount of data but followed 1/2 the screen of each cellphone. So if the phone is long, there is empty space at the bottom. If the cellphone is short, the data is cut by the screen below.
This is the code for creating bottom sheet:
void _showModalBottomSheet(AsyncSnapshot<CatlistResult> snapshot) {
showModalBottomSheet(
context: context,
builder: (BuildContext bc) {
return Card(
elevation: 3.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(topLeft: Radius.circular(15), topRight: Radius.circular(15))),
child: Container(
padding: EdgeInsets.only(left: 16.0, top: 10.0, right: 16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Container(
margin: EdgeInsets.only(bottom: 10.0),
child: Image.asset('assets/images/main/more_2lines_20dp.png', scale: 3.5),
),
Expanded(
child: GridView.builder(
physics: NeverScrollableScrollPhysics(), //kill scrollable
shrinkWrap: true,
itemCount: snapshot == null ? 0 : snapshot.data.catlist.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 4),
itemBuilder: (BuildContext context, int index) {
var numItems = snapshot.data.catlist[index];
if (numItems.f == 1) {
if (numItems.b == 0) {
return GestureDetector(
child: Card(
elevation: 0.0,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Image.asset('assets/images/main/cat_${numItems.a}.png', fit: BoxFit.cover, width: 50.0, height: 50.0),
Container(
margin: EdgeInsets.only(top: 10.0),
child: Text(
numItems.c,
maxLines: 2,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 10),
),
),
],
),
),
);
}
}
},
),
),
],
),
),
);
}
);
}
And this is the result of my code:
Run from iOS Emulator
Run from Android Emulator
Problems:
In your parent Column you are using
mainAxisSize: MainAxisSize.max
You are also using Expanded in this Column which creates the empty space if there are less items in the GridView. Remove this Expanded widget.
Solution:
Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min, // 1st use min not max
children: <Widget>[
Container(...),
GridView.builder(...), // 2nd remove Expanded
],
)