Return the scroll to the top when pressing the BottomNavigationBar item with Flutter
We will introduce an implementation that returns the scroll to the top when pressing the common BottomNavigation such as twitter.
The implementation method is easy.
1, to detect ButtomNavigation of the same element
2, to set the
scroll listener 3, to return the scroll to the top via the scroll listener
1, detect ButtomNavigation of the same element
We detect by touch event of BottomNavigation
void _selectedTab(int index) {
if (_currentTab == index) {
// ここにスクロールを戻す処理を書く
} else {
setState(() {
_currentTab = index;
});
}
}
2, set the scroll listener
First create an instance of ScrollController
final ScrollController _homeController = ScrollController();
Set Controller to the widget to be scrolled after creation.
Although this example sets Controller to CustomScrollView, it is the same for ListView and SingleChildScrollView.
body: CustomScrollView(
controller: widget._controller,
slivers: <Widget>[
SliverStaggeredGrid.countBuilder(
crossAxisCount: 2,
itemBuilder: (context, index) {
String name = index.toString();
return _itemWidget(index, "assets/$name.png");
},
staggeredTileBuilder: (int index) => const StaggeredTile.fit(1),
itemCount: 6,
),
],
),
3, scroll back to the top via the scroll listener
Next, the process of returning the scroll to the top is completed.
void _selectedTab(int index) {
if (_currentTab == index) {
_homeController.animateTo(
0.0,
curve: Curves.easeOut,
duration: const Duration(milliseconds: 300),
);
setState(() {
_currentTab = index;
});
}
}
Supplement
If you are divided into different classes according to the state of BottomNavigationItem, it is better to declare ScrollController in the parent widget and pass it to the child widget.
class Home extends StatefulWidget {
@override
_HomeState createState() => _HomeState();
}class _HomeState extends State<Home> { int _currentTab = 0; final ScrollController _homeController = ScrollController(); @override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: <Widget>[
_buildOffstage(0, Feed(_homeController)), ← 渡す
_buildOffstage(1, MyPage(_myPageController)), ← 渡す
],
),
bottomNavigationBar: FABBottomAppBar(
color: Colors.grey,
selectedColor: Colors.black,
onTabSelected: _selectedTab,
items: [
FABBottomAppBarItem(iconData: Icons.home, text: ""),
FABBottomAppBarItem(iconData: Icons.person_outline, text: ""),
],
)
);
} Widget _buildOffstage(int index, Widget page) {
return Offstage(
offstage: index != _currentTab,
child: new TickerMode(
enabled: index == _currentTab,
child: page,
),
);
} void _selectedTab(int index) {
if (_currentTab == index) {
if (index == 0) {
_homeController.animateTo(
0.0,
curve: Curves.easeOut,
duration: const Duration(milliseconds: 300),
);
} else {
_myPageController.animateTo(
0.0,
curve: Curves.easeOut,
duration: const Duration(milliseconds: 300),
);
} } else {
setState(() {
_currentTab = index;
});
}
}
}