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 HomePage
Dispose 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
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