A RenderFlex overflowed by 80 pixels on the bottom - flutter

The page got an error "A RenderFlex overflowed by 80 pixels on the bottom". How can you fix it?
class FavNews extends StatelessWidget {
final FavoritesController controller = Get.find();
FavNews({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Obx(() {
return SizedBox(
height: MediaQuery.of(context).size.height,
child: ListView.builder(
itemCount: controller.news.length,
itemBuilder: (BuildContext context, int index) {
return FavNewsItem(
article: controller.news.keys.toList()[index],
index: index,
);
}),
);
});
}
}

Put it Sizedbox inside a SingleChildScrollView widget.
return SingleChildScrollView(
child: SizedBox(
height: MediaQuery.of(context).size.height,
child: ListView.builder(
itemCount: controller.news.length,
itemBuilder: (BuildContext context, int index) {
return FavNewsItem(
article: controller.news.keys.toList()[index],
index: index,
);
}),)
Just try it. It may work

The issue is with the height of your SizedBox.
MediaQuery.of(context).size.height return the height of your entire screen including statusbar, appbar and system gestires at the bottom.
With ListView.builder you can use shrinkWrap: true that will use only the space that it acutally need to use.
Example:
return SingleChildScrollView(
child: ListView.builder(
shrinkWrap: true,
itemCount: controller.news.length,
itemBuilder: (BuildContext context, int index) {
return FavNewsItem(
article: controller.news.keys.toList()[index],
index: index,
);
}),
),
);

do not hardcoat the height while using the scrollbar remove the height attribute and it'll work just fine
final FavoritesController controller = Get.find();
FavNews({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Obx(() {
return SizedBox(
child: ListView.builder(
itemCount: controller.news.length,
itemBuilder: (BuildContext context, int index) {
return FavNewsItem(
article: controller.news.keys.toList()[index],
index: index,
);
}),
);
});
}
}```

you do not need sizedBox
return Obx(() {
return ListView.builder(
srinkWrap: true;
itemCount: controller.news.length,
itemBuilder: (BuildContext context, int index) {
return FavNewsItem(
article: controller.news.keys.toList()[index],
index: index,
);
}),);
}

Related

ListView.builder inside another ListView.builder

The listView.builder that is inside of the first, when i scroll the screen delete the data.
I used .insert that adds another widget inside the list.
in the first ListView.builder the data does not dissapear.
this what i do.
this is the first listView that keeps the data.
class _TestsPage extends State<TestsPage> with TickerProviderStateMixin {
final _commentController = TextEditingController();
bool _isWriting = false;
final List<CommentaryBox> _commentariBox = [];
#override
Widget build(BuildContext context) {
final model = Provider.of<Model>(context);
return DraggableScrollableSheet(
expand: false,
maxChildSize: 0.8,
initialChildSize: 0.6,
minChildSize: 0.6,
builder: (BuildContext context, ScrollController controller) => Column(
children: [
Expanded(
child: ListView.builder(
controller: controller,
physics: const BouncingScrollPhysics(),
itemBuilder: (_, i) => _commentariBox[i],
itemCount: _commentariBox.length,
//
reverse: false,
),
),
second listView.builder that delete data.
Visibility(
visible: _showComments,
child: ExpansionTile(
// initiallyExpanded: true,
title: _deployText
? Text('see less commentaries')
: Text('see commentaries'),
onExpansionChanged: (bool expanded) {
setState(
() {
_deployText = expanded;
},
);
},
children: [
ListView.builder(
physics: BouncingScrollPhysics(),
shrinkWrap: true,
itemBuilder: (_, i) => responseBox[i],
itemCount: responseBox.length,
reverse: true,
),
],
),
),
the way how I insert data to the list is the same for both
_handleResponse(String reply) {
final model = Provider.of<Model>(context, listen: false);
if (reply.isEmpty) return;
respController.clear();
final newAnswer = ResponseWidget(
reply: reply,
animationController: AnimationController(
vsync: this,
duration: Duration(milliseconds: 400),
),
);
responseBox.insert(0, newAnswer);
newAnswer.animationController.forward();
setState(() {
model.showComments= true;
});
}
}
I found the solution!
I just had to add this in my appState this: AutomaticKeepAliveClientMixin
in the constructor this:
#override
Widget build(BuildContext context) {
super.build(context);
and add the implemetation:
#override
// TODO: implement wantKeepAlive
bool get wantKeepAlive => true;

Flutter Listview.Builder inside bottom sheet widget not loading data on load

The below code does not display any data when the bottomsheet loads. Once the bottomsheet is loaded if I do a save operation on the code editor it loads the data. What am I missing here?
I have a bottomsheet widget which is invoked using a button.
_showBottomSheet() {
showModalBottomSheet(
context: context,
builder: (context) {
return const Contacts();
},
);
}
The above code loads up the Contacts widget that has a Listview.builder in it which is below.
class Contacts extends StatefulWidget {
const Contacts({Key? key}) : super(key: key);
#override
_ContactsState createState() => _ContactsState();
}
class _ContactsState extends State<Contacts> {
List<PhoneBookContact> phoneBookContacts1 = [];
List<PhoneBookContact> phoneBookContacts2 = [];
#override
void initState() {
loadContacts();
super.initState();
}
Future loadContacts() async {
///somecode to gather data for the listview builder
///populates the phoneBookContacts1 & phoneBookContacts2 lists
}
#override
Widget build(BuildContext context) {
return Column(children: [
const Text('Contacts Set 1'),
displayPhoneBookContacts(phoneBookContacts1),
const Text('Contacts Set 2'),
displayPhoneBookContacts(phoneBookContacts2),
]);
}
Widget displayPhoneBookContacts(phoneBookContacts) {
return Expanded(
child: ListView.builder(
shrinkWrap: true,
itemCount: phoneBookContacts.length,
itemBuilder: (BuildContext context, int index) {
return Card(
margin: const EdgeInsets.all(10),
child: ListTile(
contentPadding: const EdgeInsets.all(10),
title: Column(
children: [
Text(phoneBookContacts[index].phoneBookContact.toString()),
const SizedBox(
height: 20,
),
ListView.separated(
physics: const ClampingScrollPhysics(),
shrinkWrap: true,
itemCount: phoneBookContacts[index].contactNumbers!.length,
separatorBuilder: (BuildContext context, int index) =>
const Divider(),
itemBuilder: (BuildContext context, int phoneIndex) {
return InkWell(
onTap: () {},
child: Row(
children: [
Text(phoneBookContacts[index]
.contactNumbers![phoneIndex]
.phone),
],
),
);
},
),
],
),
),
);
},
),
);
}
}
I don't prefer using FutureBuilder inside StatefulWidget., it will recall the API(future) on every setState. As for comment it is missing setState after initializing the data.
#override
void initState() {
super.initState();
loadContacts();
}
Future loadContacts() async {
///somecode to gather data for the listview builder
///populates the phoneBookContacts1 & phoneBookContacts2
if(mounted){
// if widget build then setState call.if not we don't need to call setState
// for every initstate data loading, we have to ensure it if widget is build or not. most of the case user close screen when data loading, then error happens
setState(() {});// make sure to call setState
}
}
Because function initState() don't await your loadContacts(), data loaded after function build().
You need use FutureBuilder class to rebuild ListView widget after load data
Example:
FutureBuilder(
future: loadContacts(),
builder:(context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) {
return Center(child: CircularProgressIndicator());
} else {
return Container(
child: ListView.builder(
itemCount: _faouriteList.length,
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext context, int index) {
return Text('${_faouriteList[index].title}');
}
)
);
}
}
)

flutter widget not being updated when called from a list

i previously asked a question about widgets not being updated here:
flutter slider not updating widget variables
i got a great answer which explained to me more about how states work and i experimented a little further and now have an issue where my widget inside a list is not being updated even though i update the state in a setstate.
The Widget in question not being updated is the TestBoxNumber widget in the testBoxList list after it has been added to the list. I realize that if i change the builder to return the widget itself rather than from the list it works, and i'm not sure why this is the case!
Once again any help would be greatly appreciated and i hope this helps someone facing the same issue as well :)
Main Page Code
class TestPage extends StatefulWidget {
static const id = "test_page";
#override
_TestPageState createState() => _TestPageState();
}
class _TestPageState extends State<TestPage> {
List testBoxList = [];
List testSlideList = [];
List testParamList = [];
void updateFunc(ind, newVal) {
setState(() {
testParamList[ind] = newVal;
});
}
void addSlider() {
setState(() {
double slideValue = 0;
testParamList.add(slideValue);
int boxIndex = testParamList.length - 1;
testBoxList.add(TestBoxNumber(
numberDisplay: testParamList,
boxIndex: boxIndex,
));
testSlideList.add(TestSlider(
testValue: testParamList,
updateFunc: updateFunc,
boxIndex: boxIndex,
));
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () {
addSlider();
},
),
body: Padding(
padding: const EdgeInsets.all(30.0),
child: ListView(
children: [
Text("Test Page"),
// Builder for viewers
ListView.builder(
shrinkWrap: true,
physics: ClampingScrollPhysics(),
itemCount: testBoxList.length,
itemBuilder: (BuildContext ctx, int index) {
return testBoxList[index];
// return Text(testParamList[index].toString());
// return TestBoxNumber(
// numberDisplay: testParamList, boxIndex: index);
},
),
// Builder for sliders
ListView.builder(
shrinkWrap: true,
physics: ClampingScrollPhysics(),
itemCount: testSlideList.length,
itemBuilder: (BuildContext ctx, int index) {
return testSlideList[index];
},
),
],
),
),
);
}
}
TestBoxNumber Widget
class TestBoxNumber extends StatelessWidget {
final List numberDisplay;
final int boxIndex;
TestBoxNumber({required this.numberDisplay, required this.boxIndex});
Widget build(BuildContext context) {
return Text(this.numberDisplay[this.boxIndex].toString());
}
}
Slider Widget
class TestSlider extends StatefulWidget {
List testValue;
dynamic updateFunc;
int boxIndex;
TestSlider({
required this.testValue,
required this.updateFunc,
required this.boxIndex,
});
#override
_TestSliderState createState() => _TestSliderState();
}
class _TestSliderState extends State<TestSlider> {
// double curValue = widget.testValue;
#override
Widget build(BuildContext context) {
double curValue = widget.testValue[widget.boxIndex];
return Slider(
activeColor: themeData.primaryColorLight,
value: curValue,
min: 0,
max: 100,
divisions: 50,
label: curValue.round().toString(),
onChanged: (double value) {
setState(() {
curValue = value;
});
widget.updateFunc(widget.boxIndex, value);
},
);
}
}
Me again )
Ok, so what is wrong right now is that you are using widgets, stored in the list instead of creating ones again:
You should not do this:
ListView.builder(
shrinkWrap: true,
physics: ClampingScrollPhysics(),
itemCount: testBoxList.length,
itemBuilder: (BuildContext ctx, int index) {
return testBoxList[index];
// return Text(testParamList[index].toString());
// return TestBoxNumber(
// numberDisplay: testParamList, boxIndex: index);
},
)
but return new TestBoxNumber widgets (you actually has it commented, not sure why you did that):
ListView.builder(
shrinkWrap: true,
physics: ClampingScrollPhysics(),
itemCount: testBoxList.length,
itemBuilder: (BuildContext ctx, int index) {
return TestBoxNumber(numberDisplay: testParamList, boxIndex: index);
},
)
so you will render widgets from scratch instead of pulling it from memory (list) and causing some weird things. Flutter is pretty optimized for such re-rendering.
So summarizing all of above: just pass data into widgets in build method. Do not store widgets in memory to reuse later.
UPD: also you can just pass double (let's call it yourDoubleValue) into TestBoxNumber instead of list and index. And then use Text('$yourDoubleValue');

How to attach flutter swiper to any scroll views

How to attach flutter swiper to any scroll views?I have horizontal swiper,i scroll down my ui and then i scroll back(up), as a rezult i get Exception 'ScrollController not attached to any scroll views'.
What i should do to fix it.Could you help me?
class SwiperTop extends StatelessWidget {
MBloc _Bloc = BlocProvider.getBloc<MBloc>();
#override
Widget build(BuildContext context) {
return Container(
height: 284.0,
child: StreamBuilder(
initialData: List<MEntity>(),
stream: _mBloc.listMoviesFlux,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) return Container(height: 1, width: 1);
return Swiper(
loop: true,
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return _itemM(snapshot.data[index], context, index);
},
viewportFraction: 0.8,
scale: 0.8,
autoplay: true,
duration: 300,
autoplayDelay: 3000,
index: 0,
);
}),
);
}
}

Flutter: Create page widget as number of list size in PageView.builder

I am trying create a a pages in view pager as many as the number of item in the list of my object:
class WebViewPagerBuilder extends StatelessWidget {
final dynamic result;
const WebViewPagerBuilder({this.result});
#override
Widget build(BuildContext context) {
ProductNeedConfigModel items = result["Data"] as ProductNeedConfigModel;
return Scaffold(
body: PageView.builder(
itemCount: result["Data"].data.length,
itemBuilder: (contex, index){
[
...items.data.map((item){
return ConfigWebViewScreen(result);
})
];
}
),
);
}
}
Inside ConfigWebViewScreen class i have webview but my codes doesn't work and webview isn't shown?
********* Edit*****************
If i change my builder to this :
body: PageView.builder(
itemCount: items.data.length,
itemBuilder: (contex, index) =>
...items.data.map((item) {
return ConfigWebViewScreen(result);
}).toList()
),
a read line appear under ...items section and shows this error:
Positional arguments must occur before named arguments.
Try moving all of the positional arguments before the named arguments.
Try this,
body: PageView.builder(
itemCount: items.data.length,
itemBuilder: (contex, index) => ConfigWebViewScreen(items.data[index]),
),
),