Reputation: 92
I currently have a Homepage, which consists of a Scaffold
, with a bottomAppBar
for navigation:
The body has 5 pages, the first page is a feed, which consists of a ListView
of Widgets.
What I want to do is same as Instagram has it:
when I scroll down the feed and I click the Feed Button on the Navigation Bar, then I want the ListView
to scroll back to the top automatically.
This is part of my code:
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> with WidgetsBindingObserver {
int _selectedIndex = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
body: [
HomeFeed(),
Page2(),
...
].elementAt(_selectedIndex),
bottomNavigationBar: BottomAppBar(
child: Row(
children: <Widget>[
IconButton(
icon: FaIcon(FontAwesomeIcons.houseUser),
onPressed: (){
if (_selectedIndex == 0) {
//add logic to make the HomeFeed ListView scroll up
} else {
setState((){
_selectedIndex = 0;
});
}
},
IconButton(
icon: FaIcon(FontAwesomeIcons.compass),
onPressed: (){
setState((){
_selectedIndex = 1;
});
},
...
],
),
), //BottomAppBar
), //Scaffold
}
I know that if I had the code of the HomeFeed inside the Scaffold.body
then I could just use a Scrollcontroller
and the animateTo
method. The problem is that the Homefeed is another stateful widget and even though setState is called when clicking the feed icon, the HomeFeed widget is not rebuilding.
I tried defining a Scrollcontroller
in the Homepage and pass it to the HomeFeed but it did not work.
Can anyone help me with that?
Upvotes: 1
Views: 562
Reputation: 7119
You can set a GlobalKey
for the state of the HomeFeed
widget. Using this GlobalKey
you can call the functions of the state of the HomeFeed
widget.
Main code:
GlobalKey<HomeFeedState> feedKey = new GlobalKey<HomeFeedState>(); // this is new
@override
Widget build(BuildContext context) {
return Scaffold(
body: [
HomeFeed(key: feedKey), // this is new
Page3(),
].elementAt(_selectedIndex),
bottomNavigationBar: BottomAppBar(
child: Row(
children: <Widget>[
IconButton(
icon: FaIcon(FontAwesomeIcons.houseUser),
onPressed: (){
if (_selectedIndex == 0) {
feedKey.currentState.jumpUp(); // this is new
} else {
setState(() {
_selectedIndex = 0;
});
}
},
),
IconButton(
icon: FaIcon(FontAwesomeIcons.compass),
onPressed: (){
setState(() {
_selectedIndex = 1;
});
},
),
],
),
), //BottomAppBar
);
}
HomeFeed:
class HomeFeed extends StatefulWidget {
final GlobalKey<HomeFeedState> key; // this is new
HomeFeed({this.key}) : super(key: key); // this is new
@override
HomeFeedState createState() => HomeFeedState();
}
class HomeFeedState extends State<HomeFeed> {
var _scrollController = new ScrollController();
jumpUp() { // this will be called when tapped on the home icon
_scrollController.animateTo(0,
duration: Duration(seconds: 2), curve: Curves.ease);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
shrinkWrap: true,
controller: _scrollController,
itemCount: 100,
itemBuilder: (context, index) {
return Container(
height: 300,
child: Card(
child: Center(
child: Text('$index'),
),
),
);
},
),
);
}
}
Upvotes: 1
Reputation: 909
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> with WidgetsBindingObserver {
int _selectedIndex = 0;
Widget homeWidget = HomeFeed();
PageController pageController = PageController();
@override
Widget build(BuildContext context) {
return Scaffold(
body: PageView(
controller: pageController,
children: <Widget>[
homeWidget,
Second(),
...
],
),
bottomNavigationBar: BottomAppBar(
child: Row(
children: <Widget>[
IconButton(
icon: FaIcon(FontAwesomeIcons.houseUser),
onPressed: (){
setState((){
homeWidget = HomeFeed();
_selectedIndex = 0;
pageController.jumpToPage(0);
});
},
IconButton(
icon: FaIcon(FontAwesomeIcons.compass),
onPressed: (){
setState((){
_selectedIndex = 1;
pageController.jumpToPage(1);
});
},
...
],
),
), //BottomAppBar
), //Scaffold
}
use like this
Upvotes: 0