My app has a bottom navigation bar that shows or hides according to the direction of the scrolling:
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
class Home extends StatefulWidget {
Home({Key? key}) : super(key: key);
@override
State<Home> createState() => _HomeState();
}
class _HomeState extends State<Home> {
final ScrollController _scrollController = ScrollController();
// The item list where the data is stored.
List<String> items = [];
// Flags used to check the loading status.
bool loading = false, allLoaded = false;
// Function that loads data in the item list.
mockFetch() async {
// No more data to load.
if (allLoaded) {
return;
}
// Set the loading flag to true to prevent this function to be called several times.
setState(() {
loading = true;
});
// Simulates the delay that might occurs during an API call.
await Future.delayed(Duration(milliseconds: 500));
// If the item list is higher or equal to 60, an empty array is returned to simulate
// the end of the data stream. If not, 20 more items are generated.
List<String> newData = items.length >= 60 ? [] : List.generate(20, (index) => "List Item ${index + items.length}");
// Add the new data to the item list.
if (newData.isNotEmpty) {
items.addAll(newData);
}
// Reset the flags.
setState(() {
loading = false;
// Returns false if the array is empty.
allLoaded = newData.isEmpty;
});
}
@override
void initState() {
super.initState();
// Call the mockFetch() function when the state of MyHomePage is initialized for the first time.
mockFetch();
// Set a listener.
_scrollController.addListener(() {
if (_scrollController.position.pixels >= _scrollController.position.maxScrollExtent && !loading) {
mockFetch();
}
});
}
@override
void dispose() {
super.dispose();
_scrollController.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.deepOrange,
title: Text("Home Page"),
),
body: LayoutBuilder(builder: (context, constraints) {
if (items.isNotEmpty) {
return Stack(
// Dispay the data.
children: [
ListView.separated(
// Assign the scroll controller to the ListView.
controller: _scrollController,
itemBuilder: (context, index) {
// Display the newly loaded items.
if (index < items.length) {
return ListTile(
title: Text(items[index]),
);
}
// An extra item has been added to the index of the list meaning that
// all the items have been loaded.
else {
// Inform the user that there is no more data to load.
return Container(
width: constraints.maxWidth,
height: 50,
child: Center(
child: Text("Nothing more to load"),
),
);
}
},
// Add a separator between each item.
separatorBuilder: (context, index) {
return Divider(height: 1);
},
// Add an extra item to the length of the list when all of the items are loaded.
itemCount: items.length + (allLoaded ? 1 : 0)),
if (loading)...[
// Display a progress indicator at the bottom of the list whenever some data is loading.
Positioned(
left: 0,
bottom: 0,
child: Container(
width: constraints.maxWidth,
height: 80,
child: Center(
child: CircularProgressIndicator(),
),
)
)
]
],
);
}
else {
return Container(
child: Center(
child: CircularProgressIndicator(),
),
);
}
}
),
bottomNavigationBar: AnimatedBuilder(
animation: _scrollController,
builder: (context, child) {
return AnimatedContainer(
duration: Duration(milliseconds: 300),
height: _scrollController.hasClients && _scrollController.position.userScrollDirection == ScrollDirection.reverse ? 0: 100,
child: child,
);
},
child: BottomNavigationBar(
backgroundColor: Colors.amber[200],
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.child_friendly),
label: 'Child',
),
],
),
),
); // Scaffold
}
But when the bottom navigation bar shows or hides I get the following error
A RenderFlex overflowed by 14 pixels on the bottom.
I tried to use Expanded
, Flexible
, SingleChildScrollView
with the bottom navigation bar but I still gets this error.
Can someone show me how to fix this ?
4
Answers
Try below code and wrap your
BottomNavigationBar
insideSizedBox
and give it to height on your need, WrapSizedBox
insideSingleChildScrollView
as well.You can achieve using of
hidable 1.0.3
package for achieve the functionality.Full Code:
I’m Trying to Solve your Problem:
To fix this issue, you can try wrapping the ListView with an Expanded widget: