skip to Main Content

I am currently working on a application which has both appbar and bottom navbar. I wanted the appbar and bottom navbar hide while the user scroll. I have two screens

  1. Navbar screen : Here the code for bottom navbar and appbar is written which consists where body is the UI shown to the user.
  2. ListView Screen: This is the UI which consists a list of data.

I wanted the output like this: Image

NavBar :

class MyNavBarr extends StatefulWidget {
  const MyNavBarr({super.key});
  @override
  State<MyNavBarr> createState() => _MyNavBarrState();
}

class _MyNavBarrState extends State<MyNavBarr> {
  int _selectedIndex = 0;

  static const List<Widget> _widgetOptions = <Widget>[
    LiistView(),
    LiistView(),
    LiistView(),
    LiistView(),
  ];

  void _onItemTapped(int index) {
    setState(() {
      _selectedIndex = index;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("AppBar"),
        centerTitle: true,
      ),
      body: _widgetOptions.elementAt(_selectedIndex),
      bottomNavigationBar: SizedBox(
        height: 65.0,
        child: BottomNavigationBar(
          items: const <BottomNavigationBarItem>[
            BottomNavigationBarItem(
              icon: Icon(IconlyLight.image),
              label: '',
            ),
            BottomNavigationBarItem(
              icon: Icon(IconlyLight.video),
              label: '',
            ),
            BottomNavigationBarItem(
              icon: Icon(Icons.library_music_outlined),
              label: '',
            ),
            BottomNavigationBarItem(
              icon: Icon(IconlyLight.profile),
              label: '',
            ),
          ],
          currentIndex: _selectedIndex,
          showSelectedLabels: true,
          showUnselectedLabels: false,
          selectedFontSize: 0.0,
          type: BottomNavigationBarType.fixed,
          onTap: _onItemTapped,
        ),
      ),
    );
  }
}

ListView :


class LiistView extends StatefulWidget {
  const LiistView({super.key});

  @override
  State<LiistView> createState() => _LiistViewState();
}

class _LiistViewState extends State<LiistView> {

  final controller = ScrollController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ListView.builder(
        itemCount: 80,
        itemBuilder: (context, index){
          return const ListTile(
            title: Text("Abcd"),
          );
        },

      ),
    );
  }
}

3

Answers


  1. You can achieve this using the Hideable library.

    Create a Scroll Controller and pass it to the scrollable widget

    final ScrollController scrollController = ScrollController();
    
    ListView(
     controller: scrollController,
     ...
    )
    

    Wrap your BottomNavigationBar with Hideable

    Hidable(
     controller: scrollController,
     wOpacity: true, // default
     child: BottomNavigationBar(...),
    )
    
    Login or Signup to reply.
  2. The easiest way to do so is that,

    ScrollController _hideButtonController;
    
      bool _isVisible = true;
      @override
      void initState() {
        super.initState();
        _isVisible = true;
        _hideButtonController = new ScrollController();
        _hideButtonController.addListener(() {
          print("listener");
          if (_hideButtonController.position.userScrollDirection ==
              ScrollDirection.reverse) {
            setState(() {
              _isVisible = false;
              print("**** $_isVisible up");
            });
          }
          if (_hideButtonController.position.userScrollDirection ==
              ScrollDirection.forward) {
            setState(() {
              _isVisible = true;
              print("**** $_isVisible down");
            });
          }
        });
      }
    

    Wrap your bottom Nav bar with animated container same as below

    AnimatedContainer(
            duration: Duration(milliseconds: 200),
            height: _isVisible ? 60 : 0.0,
            child: BottomNavBarCode......,
          ),
    

    Build your list view and app bar same as below

    CustomScrollView(
            controller: _hideButtonController,
            slivers: <Widget>[
              SliverAppBar(
                expandedHeight: 150,
                pinned: true, // กำหนดว่าจะให้ pin appbar ไว้บางส่วนไหม หรือ ให้หายไปหมด
                floating: true,
                snap: true,
                flexibleSpace: FlexibleSpaceBar(
                  title: Text(widget._grassroot.name),
                  // title: Text('GRASSROOT ENGINEER'),
                ),
              ),
              SliverList(
                delegate: SliverChildBuilderDelegate(
                  //YOUR_LIST_VIEW_CODE,
                  childCount: exercises.length),
              ),
            ],
          ),
        )
    
    Login or Signup to reply.
  3. You can add a listener to the scrollController. And then Update the UI based on the user scroll input.

    Try something like below.

      ScrollController scrollController = ScrollController();
    
     @override
      void initState() {
        super.initState();
        scrollController.addListener(_updateScrollController);
      }
    
    
    
     void _updateScrollController() async {
        if (!mounted) {
          return;
        }
        if (scrollController.position.pixels < -100) {
          if (!showSearchbar) {
            HapticFeedback.heavyImpact();
            
            setState(() {
    
              showSearchbar = true;
            });
          }
        } else if (scrollController.position.pixels > 50) {
          if (showSearchbar) {
            HapticFeedback.heavyImpact();
            setState(() {
              showSearchbar = false;
            });
          }
        }
      }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search