Losyres
Losyres

Reputation: 92

Flutter: Change Scroll Offset in a child through NavigationBar

I currently have a Homepage, which consists of a Scaffold, with a bottomAppBar for navigation:

Navigation Bar

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

Answers (2)

Mobina
Mobina

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

Johny Saini
Johny Saini

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

Related Questions