The following assertion was thrown while applying parent data.:
Incorrect use of ParentDataWidget.
The ParentDataWidget Flexible(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 Flexible widget has the wrong ancestor RenderObjectWidget. Typically, Flexible widgets are placed directly inside Flex widgets.
The offending Flexible is currently placed inside a RepaintBoundary widget.
My Code is
class Search extends StatelessWidget {
//final homeProvider;
final HomeProvider homeProvider;
Search(this.homeProvider);
#override
Widget build(BuildContext context) {
return Container(
child: SmartRefresher(
controller: homeProvider.getSearchRefreshControllerLook(),
enablePullDown: true,
enablePullUp: true,
onRefresh: () {
debugPrint('on pull to refresh ');
//modistaboxApplicationProvider.getTrendingLooksWithLoginStatus();
homeProvider.getAllLooks();
},
onLoading: () {
debugPrint('next loading --------- ');
homeProvider.getAllNextLooks();
},
child: ListView(
controller: homeProvider.controllerLooksList,
children: [
Selector<HomeProvider, NetWorkResponseStatus>(
builder: (context, data, child) {
Widget lookWidget;
switch (data) {
case NetWorkResponseStatus.ResponseError:
lookWidget = Column(
children: <Widget>[
SizedBox(
height: MediaQuery.of(context).size.height / 3,
),
const ModistaboxErrorWidget(
error: 'No Internet',
visible: true,
)
],
);
break;
case NetWorkResponseStatus.ResponseEmpty:
lookWidget = const EmptyWidget(
visible: true,
);
break;
case NetWorkResponseStatus.NetworkError:
lookWidget = const EmptyWidget(
visible: true,
);
break;
case NetWorkResponseStatus.ResponseData:
lookWidget = getLooksWidget(context, homeProvider);
break;
default:
lookWidget = Column(
children: <Widget>[
SizedBox(
height: MediaQuery.of(context).size.height / 3,
),
Center(child: CustomProgressIndicator())
],
);
break;
}
return Padding(
padding: const EdgeInsets.only(left: 5, right: 5),
child: lookWidget,
);
},
selector: (buildContext, provider) => homeProvider.lookResponseStatus),
],
),
),
);
}
Widget getLooksWidget(context, HomeProvider homeProvider) {
return homeProvider.lookListResponce != null &&
homeProvider.lookListResponce.results.length > 0
? GridView.builder(
shrinkWrap: true,
itemCount: homeProvider.lookListResponce.results.length,
scrollDirection: Axis.vertical,
physics: const ScrollPhysics(),
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
crossAxisSpacing: 5,
mainAxisSpacing: 5,
childAspectRatio: 2 / 3,
),
itemBuilder: (BuildContext context, int index) {
return lookWidget(index, context,
homeProvider.lookListResponce.results[index], homeProvider);
},
)
: const EmptyWidget(
visible: true,
);
}
Widget lookWidget(int index, context, ResultsLook look,
HomeProvider homeProvider) {
return Stack(
children: <Widget>[
InkWell(
onTap: () {
debugPrint('look data --- $look');
Navigator.pushNamed(context,TagrankRoutes.lookTagging,arguments:
look.image);
},
child: CachedNetworkImage(
imageUrl: look.image,
fit: BoxFit.fitHeight,
height: (MediaQuery.of(context).size.height) - 80),
),
Positioned(
left: 5,
bottom: 5,
child: InkWell(
onTap: () {
//debugPrint("this is inkwell");
if (TagRankPreferences().getLoginStatus()) {
} else {
Fluttertoast.showToast(msg: 'Please login to see user profile');
}
},
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
SizedBox(
width: 5,
),
Text(
look.username ?? '',
style: textStyle12White,
),
],
),
),
),
Positioned(
child: Container(
height: 16,
width: 16,
child: Checkbox(
checkColor: Colors.red ,
activeColor: Colors.white
//checkColor: dividerColor,
onChanged:(newValue){
homeProvider.onClickCheckBox(look);
},
value: true,
),
),
/*child: Row(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
*//* InkWell(
child: Icon(
Icons.share,
color: white,
),
),*//*
],
),*/
right: 5,
bottom: 5,
)
],
);
}
}
Apparently, you forgot to post the actual code with Flexible.
It seems that you provide the only Flexible widget in the container, so it does not understand what space it should allocate. To fix that, add another Flexible in a Row or a Column so that Flutter knows the proportion of the space you want to dedicate to your widget.
Here is the example of the code:
Row(
children: [
Flexible(
flex: 1,
child: Container() // your widget here
),
Flexible(
flex: 2,
child: Container() // another widget or an empty container to allocate the space
),
],
);
See also: Flutter Flexible.
Your code is missing the flexible widget which you are trying to explain.
If you are trying to use ListView inside a Flexible or Expanded widget this kind of error is shown. Because it can accept only row, column, or flex.
Try to use a ConstrainedBox or container with a fixed height/width
ConstrainedBox(
constraints: BoxConstraints(minHeight: 50, maxHeight: 500),
child: ListView(...),
)
Related
I am trying to find a way to have two ListView as children of a Row to have matching heights. This means if one ListView is shorter than the other one, then it must stretch until it matches the other ListView's height.
Schematically speaking this is what I have now:
How can I have the green ListView to match the orange's ListView's height?
This is my row at the moment:
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildList(list: listA), // returns a `ListView` wrapped in `Card`
_buildList(list: listB),
],
)
I tried setting crossAxisAlignment to CrossAxisAlignment.strech but it causes an error with this message:
A RenderBox object must have an explicit size before it can be hit-tested. Make sure that the RenderBox in question sets its size during layout.
I believe it means that one of the child can't ascertain its height...
After following pskink suggestion to use IntrisictHeight, albeit very expensive as per the documentation, I managed to make it work by replacing my ListViews with Columns.
Indeed, as my list are quite short (as explained in my OP), there is no need for ListView with scrolls, animation, recycling, etc.
Using Column was also the only way to make it work with IntrisictHeight anyway.
So this is the solution I retained:
IntrinsicHeight(
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
_buildList(listA),
_buildList(listB),
],
),
Widget _buildList(List<String> list) {
return Container(
width: 400,
margin: const EdgeInsets.only(left: 8, right: 8),
child: Card(
elevation: 10,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_SkillType(name: skillType),
for (final Text in list) Text(text),
],
),
);
}
All thanks go to pskink.
You can wrap your ListView with Expanded widget
_buildList({required List<String> list}) {
return Expanded(
child: Container(
color: Colors.cyanAccent,
child: ListView.builder(
itemCount: list.length,
itemBuilder: (context, index) => ListTile(
title: Text(list[index]),
),
),
),
);
}
Also provide ScrollController to listview to avoid getting error
class Home extends StatefulWidget {
#override
State<Home> createState() => _HomeState();
}
class _HomeState extends State<Home> {
List<String> listData = List.generate(10, (index) => '$index');
List<String> listData2 = List.generate(5, (index) => '$index');
List<TextEditingController> listDataCTL = [];
ScrollController controler = new ScrollController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('AppBar'),
),
body: SingleChildScrollView(
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Flexible(
child: Card(
color: Colors.yellow,
child: ListView.builder(
controller: controler,
itemCount: listData.length,
shrinkWrap: true,
itemExtent: (listData.length < listData2.length) ? listData2.length / listData.length * 50 : 50,
itemBuilder: (context, index) {
return Container(
color: Colors.blue,
margin: EdgeInsets.symmetric(vertical: 4),
child: Text('Item'),
);
},
),
),
),
Flexible(
child: Card(
color: Colors.green,
child: ListView.builder(
controller: controler,
itemCount: listData2.length,
itemExtent: (listData.length > listData2.length) ? listData.length / listData2.length * 50 : 50,
shrinkWrap: true,
itemBuilder: (context, index) {
return Container(
margin: EdgeInsets.symmetric(vertical: 4),
color: Colors.red,
child: Text('Item'),
);
},
),
),
),
],
),
));
}
}
When listData.length> listData2.length
When listData2.length> listData.length
UPDATE:
Scaffold(
appBar: AppBar(
title: Text('AppBar'),
),
body: Card(
child: Row(
children: [
_buildList(list: listData, compareList: listData2),
_buildList(list: listData2, compareList: listData),
],
),
),
)
_buildList({List<String> list, List<String> compareList, double itemExtent = 50, double spacing = 8}) {
return Flexible(
child: GridView.builder(
shrinkWrap: true,
padding: EdgeInsets.all(0),
physics: const NeverScrollableScrollPhysics(),
itemCount: list.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 1,
crossAxisSpacing: 0,
mainAxisSpacing:
(list.length < compareList.length) ? (((compareList.length - list.length) * itemExtent) + ((compareList.length - 1) * spacing)) / 4 : spacing,
mainAxisExtent: itemExtent,
),
itemBuilder: (context, index) {
return Container(
color: Colors.red.withOpacity(0.3 + ((index * 5) / 100)),
margin: EdgeInsets.symmetric(vertical: 0),
child: Text('Item'),
);
},
),
);
}
I think you want this version:
_buildList({List<String> list, List<String> compareList, double itemExtent = 50, double spacing = 8}) {
return Flexible(
child: Card(
child: ListView.builder(
itemCount: list.length,
shrinkWrap: true,
padding: EdgeInsets.only(
bottom: (list.length < compareList.length) ? (((compareList.length - list.length) * itemExtent) + ((compareList.length - 1) * 0)) : 0,
),
physics: const NeverScrollableScrollPhysics(),
itemExtent: itemExtent,
itemBuilder: (context, index) {
return Container(
color: Colors.red.withOpacity((index * 5) / 100),
margin: EdgeInsets.symmetric(vertical: 0),
child: Text('Item'),
);
},
),
),
);
}
I am facing issue When keyboard open/close at that time ChangeNotifierProvider call multiple time so my full screen reload multiple time. In this widget I have attach video so widget is calling so many times then my instance is fail.
return Scaffold(
backgroundColor: ColorManager.colorBackgroundGray,
body: ChangeNotifierProvider<CreateRouteStep2ViewModel>(
create: (BuildContext context) => modelProvider,
builder: (context, snapshot) {
printValue(label: "ChangeNotifierProvider", value: "");
return Consumer<CreateRouteStep2ViewModel>(
builder: (context, provider, c) {
return SizedBox(
height: double.infinity,
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Stack(
children: [
provider.viewType == CreateRouteStep2ViewType.map
? SizedBox(
height: 300,
child: GoogleMapForCreateRoute(
modelProvider: modelProvider),
)
: const SizedBox(),
],
),
)
],
),
Expanded(
flex: 1,
child: Container(
color: ColorManager.colorWhite,
child: SingleChildScrollView(
child: ListView.builder(
shrinkWrap: true,
physics:
const NeverScrollableScrollPhysics(),
padding: const EdgeInsets.only(top: 10),
itemCount: provider.listRouteName.length,
itemBuilder: (BuildContext context, index) {
return CreateStepsItem(
routeModel:
provider.listRouteName[index],
modelProvider: modelProvider,
index: index,
removeIndex: () {
// Todo Remove index from marker pin and location array.
modelProvider
.removeIndexFromPinAndList(index);
},
edtLocationNameFocus: () {
modelProvider.focusMap(index);
},
edtAudioFocus:
(mainPosition, subPosition) {
modelProvider.focusAudioComponent(
index, subPosition);
},
edtVideoFocus:
(mainPosition, subPosition) {
modelProvider.focusVideoComponent(
index, subPosition);
},
);
},
scrollDirection: Axis.vertical,
),
),
)),
Visibility(
visible:
MediaQuery.of(context).viewInsets.bottom == 0,
child: Align(
alignment: Alignment.bottomCenter,
child: Padding(
padding: const EdgeInsets.only(
left: 24.0, right: 24.0, bottom: 20.0),
child: CommonButton(
onPressed: () {},
lable: AppStrings.constTourSpichern,
isEnable: false,
),
),
),
)
],
),
),
const SizedBox(
height: 20,
)
],
),
);
});
}),
);
Is there any widget behaviour is attach with keyboard?. If any one know that then please let me know.
I have this screen with a searchWidget on top and a list below it. But the list data comes after querying in the searchWidget, and while waiting for the data to be fetched i want to render a ActivityIndicator at the center of the screen. But the progress indicator doesn't seem to take the rest of the space of the screen and it's directly below the searchWidget, and if i wrap it inside an Expanded it gives an error
body: SingleChildScrollView(
physics: BouncingScrollPhysics(),
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
SearchWidget(
hintText: 'Search',
textEditingController: _textEditingController,
onCancel: () {
setState(() {
_textEditingController.text = '';
data = [];
});
},
onSubmitted: (val) {
onSubmitted(val);
}),
_isLoading
? (Container(
child: Center(
child: CupertinoActivityIndicator(
radius: 15,
),
),
))
: (data.length == 0
? SizedBox()
: Padding(
padding:
const EdgeInsets.only(top: 8, right: 8, left: 8),
child: ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: data.length,
itemBuilder: (ctx, i) =>
ListItem(item: data[i]),
),
))
],
),
),
Try Expanded:
_isLoading
? (Expanded(
child: Center(
child: CupertinoActivityIndicator(
radius: 15,
),
),
))
Put your CupertinoActivityIndicator inside a Column and use Spacer to put it in the middle of the screen. Just like this:
Column(
children: [
Spacer(),
Container(
child: Center(
child: CupertinoActivityIndicator(
radius: 15,
),
),
),
Spacer()
]
)
I want to create 2 list type data
first linear and other grid type list
now requirement is that both data list height will be dynamic means it should be expand when , new object is added.
and sorting scrollable along with all 4 widgets(sort, list, sort, grid).
like below image:
i have tried but height is static ,
i have used expanded but not giving result as i'm expecting.
code:
Container(
padding: EdgeInsets.all(10),
child: Container(
child: Column(
children: [
sort(context),//sort widget
createForlderView(context), //dynamic list widget
sort(context), //sort widget
_createGridView()// dynamic grid list widget
],
),
),
);
Widget sort(BuildContext context){
return Container(
// color: Colors.red,
height: 25,
width: MediaQuery.of(context).size.width,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text("Folder"),
Container(
// color:Colors.green,
width: 60,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text("Sort"),
// SizedBox(width:5),
InkWell(onTap: () {}, child: Icon(Icons.sort))
],
),
),
],
),
);
}
// list view:
Widget createForlderView(BuildContext context) {
final _width = MediaQuery.of(context).size.width;
final _height = MediaQuery.of(context).size.height;
return Expanded(
child: Container(
height: _height / 1.2,
child: ListView.builder(
// padding: ,
itemCount: directoryItems.length,
itemBuilder: (context, index) {
return Card(
child: ListTile(
leading: Container(
height: 30,
width: 30,
child: Icon(Icons.folder, color: Colors.brown),
),
title: Text(directoryItems[index]),
subtitle: Text("15 items"),
trailing:
IconButton(icon: Icon(Icons.more_vert), onPressed: () {}),
));
}),
),
);
}
// grid view:
Widget _createGridView() {
var mSize = MediaQuery.of(context).size;
/*24 is for notification bar on Android*/
final double itemHeight = (mSize.height - kToolbarHeight) / 2;
final double itemWidth = mSize.width / 2;
int gridItemCount =
Provider.of<DocumentProvider>(context).allDocuments.length;
return Expanded(
child: Container(
height: 100,
child: GridView.count(
key: animatedListKey,
scrollDirection: Axis.vertical, //default
reverse: false,
crossAxisCount: 2,
crossAxisSpacing: 4.0,
mainAxisSpacing: 4.0,
childAspectRatio: (itemWidth / itemHeight),
children: List.generate(gridItemCount, (index) {
return Center(
child: SelectCard(
index: index,
itemHeight: itemHeight,
itemWidth: itemWidth,
deletefun: () {
Navigator.pop(context);
DeleteDialog(
index: index,
dateTime:
Provider.of<DocumentProvider>(context, listen: false)
.allDocuments[index]
.dateTime);
},
),
);
}),
),
),
);
}
output screen:
I have found my solution,
used CustomScrollView along with it's slivers: SliverToBoxAdapter (for single widget),SliverFixedExtentList (for linear list) , and SliverGrid (for Grid list).
import 'package:flutter/material.dart';
class ExpandableList extends StatefulWidget {
final List<FolderModel> listData;
final List<FilesModel> gridListData;
const ExpandableList({Key key, this.listData, this.gridListData}) : super(key: key);
#override
_ExpandableListState createState() => _ExpandableListState();
}
class _ExpandableListState extends State<ExpandableList> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: <Widget>[
buildAppBar(),
sorting(title: "folders", tralingTitle: "sort", onTap: (){}),
expandableListBuilder(),
sorting(title: "files", tralingTitle: "sort",onTap: (){}),
expandableGridList(),
],
)
);
}
buildAppBar(){
return SliverAppBar(
title: Text("Multi Expandable list example"),
centerTitle: true,
pinned: true,
);
}
expandableListBuilder(){
return SliverFixedExtentList(
itemExtent: 75.0,
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Card(
child: ListTile(
leading: Container(
height: 30,
width: 30,
child: Icon(Icons.folder, color: Colors.brown),
),
title: Text(widget.listData[index].title),
subtitle: Text(widget.listData[index].subtitle),
trailing:
IconButton(icon: Icon(Icons.more_vert), onPressed: () {}),
));
},
childCount: widget.listData.length
),
);
}
expandableGridList(){
return SliverGrid(
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 200.0,
mainAxisSpacing: 10.0,
crossAxisSpacing: 10.0,
),
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Card(
elevation: 8,
child: Container(
alignment: Alignment.center,
height: 100,
width: 100,
child: Text("${widget.gridListData[index].title}${(index+1).toString()}"),
),
);
},
childCount: widget.gridListData.length,
),
);
}
sorting({String title,String tralingTitle, void Function() onTap}){
return SliverToBoxAdapter(
child: Container(
padding: const EdgeInsets.all(10),
height: 50,
width: MediaQuery.of(context).size.width,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(title),
Container(
// color:Colors.green,
width: 60,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(tralingTitle),
// SizedBox(width:5),
InkWell(
onTap:onTap,
child: Icon(Icons.sort))
],
),
),
],
),
),
);
}
}
result:
I have a gridlayout with griditems being basically :
Cards
with two things :
Image
Text
But the image is being loaded through the internet hence sometimes it overflows the grid item box and this box does not change the height, what i want is the image should be of fixed size.
Here is my code : (How do i do it ? )
import 'package:flutter/material.dart';
import '../models/dbModel.dart';
class GridLayout extends StatelessWidget {
final List<DbModel> m;
var appContext;
GridLayout(this.m, this.appContext);
Widget build(context) {
return GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2, crossAxisSpacing: 7.0, mainAxisSpacing: 7.0),
padding: const EdgeInsets.all(10.0),
itemBuilder: (context, i) {
return GridItem(appContext, m[i]);
},
itemCount: m.length,
);
}
}
class GridItem extends StatelessWidget {
final appContext;
final dbModel;
GridItem(this.appContext, this.dbModel);
Widget build(context) {
return GestureDetector(
onTap: () {},
child: Card(
child: Column(
children: <Widget>[
dbModel.img == "NOLINK" ? Image.network("https://i.ibb.co/Vv6cPj4/404.png",) : Image.network(dbModel.img),
Container(
padding: EdgeInsets.all(10.0),
child: Text("${dbModel.title}"),
),
],
),
),
);
}
}
you need wrap image widget - Image.network with Expanded & add fit: BoxFit.cover,.
working code:
Widget build(context) {
return GestureDetector(
onTap: () {},
child: Card(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch, //add this
children: <Widget>[
Expanded(
child: Image.network(
"https://i.ibb.co/Vv6cPj4/404.png",
fit: BoxFit.cover, // add this
),
),
Center(
child: Container(
padding: EdgeInsets.all(10.0),
child: Text("Title under"),
),
),
],
),
),
);
}
output:
Use Container and Inside a container declare the width and height of the image as
you want.
new Container(
width: 60.0
height: 60.0,
decoration: new BoxDecoration(
image: new DecorationImage(
image:Image.network("https://i.ibb.co/Vv6cPj4/404.png",),
//repeat: ImageRepeat.repeat,
),
),
)
I hope, this will help you.