Saltar al contenido

Ocultar la barra de navegación inferior al desplazarse hacia abajo y viceversa

Hemos investigando en el mundo on line para brindarte la respuesta para tu inquietud, en caso de alguna pregunta deja tu pregunta y respondemos sin falta.

Solución:

Si bien la solución de Naveen funciona perfectamente, no me gustó la idea de usar setState para manejar la visibilidad de la barra de navegación. Cada vez que el usuario cambiaba la dirección de desplazamiento, se reconstruía toda la página de inicio, incluida la barra de aplicaciones y el cuerpo, lo que puede ser una operación costosa. Creé una clase separada para manejar la visibilidad que usa un ValueNotifier para rastrear el estado oculto actual.

class HideNavbar 
  final ScrollController controller = ScrollController();
  final ValueNotifier visible = ValueNotifier(true);

  HideNavbar() 
    visible.value = true;
    controller.addListener(
      () 
        if (controller.position.userScrollDirection ==
            ScrollDirection.reverse) 
          if (visible.value) 
            visible.value = false;
          
        

        if (controller.position.userScrollDirection ==
            ScrollDirection.forward) 
          if (!visible.value) 
            visible.value = true;
          
        
      ,
    );
  

  void dispose() 
    controller.dispose();
    visible.dispose();
  

Ahora todo lo que debe hacer es crear una instancia final de HideNavbar en su widget de HomePage.

final HideNavbar hiding = HideNavbar();

Ahora pase la instancia ScrollController al ListView o CustomScrollView cuerpo de tu Scaffold.

body: CustomScrollView(
          controller: hiding.controller,
          ...

Entonces rodea tu bottomNavigationBar con un ValueListenableBuilder que toma el ValueNotifier desde el HideNavbar instancia y luego establezca la propiedad de altura de bottomNavigationBar en 0 o cualquier otro valor dependiendo del estado de la ValueNotifier.

bottomNavigationBar: ValueListenableBuilder(
        valueListenable: hiding.visible,
        builder: (context, bool value, child) => AnimatedContainer(
          duration: Duration(milliseconds: 500),
          height: value ? kBottomNavigationBarHeight : 0.0,
          child: Wrap(
            children: [
              BottomNavigationBar(
                type: BottomNavigationBarType.fixed,
                backgroundColor: Colors.blue,
                fixedColor: Colors.white,
                unselectedItemColor: Colors.white,
                items: const [
                  BottomNavigationBarItem(
                    icon: Icon(Icons.home),
                    title: Text('Home'),
                  ),
                  BottomNavigationBarItem(
                    icon: Icon(Icons.card_giftcard),
                    title: Text('Offers'),
                  ),
                  BottomNavigationBarItem(
                    icon: Icon(Icons.account_box),
                    title: Text('Account'),
                  ),
                ],
              ),
            ],
          ),
        ),
      ),

Este enfoque evita innumerables reconstrucciones y no requiere bibliotecas externas. También puede implementar esto como un enfoque basado en flujo, pero eso requeriría otra biblioteca como dart:async y no cambiaría nada. Asegúrese de llamar a la función de eliminación de HideNavbar dentro HomePageDispose función para borrar todos los recursos utilizados.

Aquí está el código.

void main() => runApp(MaterialApp(home: Scaffold(body: MyApp())));

class MyApp extends StatefulWidget 
  @override
  _MyAppState createState() => _MyAppState();


class _MyAppState extends State 
  ScrollController _scrollController;
  double _containerMaxHeight = 56, _offset, _delta = 0, _oldOffset = 0;

  @override
  void initState() 
    super.initState();
    _offset = 0;
    _scrollController = ScrollController()
      ..addListener(() 
        setState(() 
          double offset = _scrollController.offset;
          _delta += (offset - _oldOffset);
          if (_delta > _containerMaxHeight)
            _delta = _containerMaxHeight;
          else if (_delta < 0) _delta = 0;
          _oldOffset = offset;
          _offset = -_delta;
        );
      );
  

  @override
  Widget build(BuildContext context) 
    return LayoutBuilder(
      builder: (context, constraints) 
        return Stack(
          alignment: Alignment.bottomCenter,
          children: [
            ListView.builder(
              physics: ClampingScrollPhysics(),
              controller: _scrollController,
              itemCount: 20,
              itemBuilder: (context, index) => ListTile(title: Text(index.toString())),
            ),
            Positioned(
              bottom: _offset,
              width: constraints.maxWidth,
              child: Container(
                width: double.infinity,
                height: _containerMaxHeight,
                color: Colors.grey[300],
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  children: [
                    _buildItem(Icons.home, "Home"),
                    _buildItem(Icons.blur_circular, "Collection"),
                    _buildItem(Icons.supervised_user_circle, "Community"),
                    _buildItem(Icons.notifications, "Notifications"),
                  ],
                ),
              ),
            ),
          ],
        );
      ,
    );
  

  Widget _buildItem(IconData icon, String title) 
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Icon(icon, size: 28),
        Text(title, style: TextStyle(fontSize: 10)),
      ],
    );
  

Nota: Lo intenté bottomNavigationBar pero las cosas no funcionaban como se esperaba, así que creé una especie de mi propia barra de navegación inferior y puedes modificar el código aún más para tu uso.

Captura de pantalla

ingrese la descripción de la imagen aquí

Código de trabajo con BottomNavigationBar.

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

void main() 
  runApp(MyApp());


class MyApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo'),
    );
  


class MyHomePage extends StatefulWidget 
  MyHomePage(Key key, this.title) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();


class _MyHomePageState extends State 
  ScrollController _hideBottomNavController;

  bool _isVisible;

  @override
  initState() 
    super.initState();
    _isVisible = true;
    _hideBottomNavController = ScrollController();
    _hideBottomNavController.addListener(
      () 
        if (_hideBottomNavController.position.userScrollDirection ==
            ScrollDirection.reverse) 
          if (_isVisible)
            setState(() 
              _isVisible = false;
            );
        
        if (_hideBottomNavController.position.userScrollDirection ==
            ScrollDirection.forward) 
          if (!_isVisible)
            setState(() 
              _isVisible = true;
            );
        
      ,
    );
  

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: CustomScrollView(
          controller: _hideBottomNavController,
          shrinkWrap: true,
          slivers: [
            SliverPadding(
              padding: const EdgeInsets.all(10.0),
              sliver: SliverList(
                delegate: SliverChildBuilderDelegate(
                  (context, index) => _getItem(context),
                  childCount: 20,
                ),
              ),
            ),
          ],
        ),
      ),
      bottomNavigationBar: AnimatedContainer(
        duration: Duration(milliseconds: 500),
        height: _isVisible ? 56.0 : 0.0,
        child: Wrap(
          children: [
            BottomNavigationBar(
              type: BottomNavigationBarType.fixed,
              backgroundColor: Colors.blue,
              fixedColor: Colors.white,
              unselectedItemColor: Colors.white,
              items: [
                BottomNavigationBarItem(
                  icon: Icon(Icons.home),
                  title: Text('Home'),
                ),
                BottomNavigationBarItem(
                  icon: Icon(Icons.card_giftcard),
                  title: Text('Offers'),
                ),
                BottomNavigationBarItem(
                  icon: Icon(Icons.account_box),
                  title: Text('Account'),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  

  _getItem(BuildContext context) 
    return Card(
      elevation: 3,
      margin: EdgeInsets.all(8),
      child: Row(
        children: [
          Expanded(
            child: Container(
              padding: EdgeInsets.all(8),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Padding(
                    padding: const EdgeInsets.all(8.0),
                    child: Text(
                      'Item',
                      style:
                          TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
                    ),
                  )
                ],
              ),
            ),
          ),
        ],
      ),
    );
  

Modelo de trabajo

Comentarios y calificaciones del tutorial

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *