I am working on a nested listview
in flutter, I did it like below.
class _SearchResultState extends State<SearchResult> {
late String searchValue;
@override
void initState() {
// TODO: implement initState
super.initState();
searchValue = widget.searchValue;
searchData = widget.searchValue;
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
backgroundColor: Colors.white,
body: SafeArea(
child: SingleChildScrollView(
child: Column(
children: [
SearchBox(),
WordDetails(),
const SizedBox(height: 5),
DictionaryUsersList(),
WordMeaning(),
],
),
),
)
);
}
}
class WordMeaning extends StatelessWidget {
WordMeaning({super.key});
final json = <Map<String, dynamic>>[
{
'type': 'adjective',
'meaning': [
{
'description': 'description 1',
'example': 'example 1',
},
{
'description': 'description 2',
'example': 'example 2',
},
{
'description': 'description 3',
'example': 'example 3',
},
{
'description': 'description 4',
'example': 'example 4',
},
],
},
{
'type': 'noun',
'meaning': [
{
'description': 'description 1',
'example': 'example 1',
},
{
'description': 'description 2',
'example': 'example 2',
},
],
},
{
'type': 'verb',
'meaning': [
{
'description': 'description 1',
'example': 'example 1',
},
],
},
{
'type': 'adverb',
'meaning': [
{
'description': 'description 1',
'example': 'example 1',
},
{
'description': 'description 2',
'example': 'example 2',
},
{
'description': 'description 3',
'example': 'example 3',
},
],
},
];
@override
Widget build(BuildContext context) {
List<Word> words = json.map((json) => Word.fromJson(json)).toList();
return NestedListView(data: words);
}
}
class NestedListView extends StatelessWidget {
final List<Word> data;
const NestedListView({
Key? key,
required this.data,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Expanded(
child: SizedBox(
child: ListView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: data.length,
itemBuilder: (context, index) {
List<Meaning> innerList = data[index].meaning;
return Expanded(
child: SizedBox(
height: 80,
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(4.0),
child: Text(data[index].type.toString().toUpperCase()),
),
Expanded(
child: ListView.builder(
shrinkWrap: true,
itemCount: innerList.length,
itemBuilder: (context, index) {
final product = innerList[index];
return Padding(
padding: const EdgeInsets.all(4.0),
child: Container(
color: Colors.grey,
child: Column(
children: [
Text(product.description),
Text(product.example),
],
)),
);
},
),
),
],
),
),
);
},
),
),
),
);
}
}
I have 2 issues with this UI.
- The inner listview is not fully visible. Please check the below screenshot.
- Getting below error when running the application:
======== 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 ParentData.
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 RepaintBoundary widget.
I tried wrapping the Expanded
widget with a Column
like below:
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Column(
children: [
Expanded(
child: SizedBox(
child: ListView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: data.length,
itemBuilder: (context, index) {
List<Meaning> innerList = data[index].meaning;
return SizedBox(
height: 80,
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(4.0),
child: Text(data[index].type.toString().toUpperCase()),
),
Expanded(
child: SizedBox(
height: 80,
child: ListView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: innerList.length,
itemBuilder: (context, index) {
final product = innerList[index];
return Padding(
padding: const EdgeInsets.all(4.0),
child: Container(
color: Colors.grey,
child: Column(
children: [
Text(product.description),
Text(product.example),
],
),
),
);
},
),
),
),
],
),
);
},
),
),
),
],
),
);
}
But at that time getting another error like below:
======== Exception caught by rendering library =====================================================
The following assertion was thrown during paint():
RenderBox was not laid out: RenderRepaintBoundary#50ab9 relayoutBoundary=up2 NEEDS-PAINT
‘package:flutter/src/rendering/box.dart’:
Failed assertion: line 1966 pos 12: ‘hasSize’
Either the assertion indicates an error in the framework itself, or we should provide substantially more information in this error message to help you determine and fix the underlying cause.
2
Answers
You’ve used
Expanded
widget inListView
and inSingleScrollChildView
, it is only applicable inRow
andColumn
. Simply removeExpanded
from these and it will be fixed.The more you go nested, the more complex is to handle the UI. Try to modify like below. You need to do fourchanges.
Remove
SingleChildScrollView
,Expanded
,SizedBox
and keep it as a simple hierarchy.Add
physics
for InnerListview
.Set
mainaxis
size forColumn
Wrap
Wordmeaning()
class withExpanded
// No change here
}
}
This should build your UI as expected. Let me know if that works.