在 Flutter 中的 Scroll 上隐藏底部导航栏
Posted
技术标签:
【中文标题】在 Flutter 中的 Scroll 上隐藏底部导航栏【英文标题】:Hide Bottom Navigation bar on Scroll in Flutter 【发布时间】:2018-10-25 11:46:12 【问题描述】:我在正文和底部导航栏中有一个博客文章列表。我想在帖子列表向下滚动时用向下滑动动画隐藏底部导航栏,并在向上滚动时用向上滑动动画显示。怎么做?
【问题讨论】:
你能出示代码吗 你可以按照我上面所说的举自己的例子。 【参考方案1】:此解决方案只是解决此问题的方法。 可能会有一些不利的变化。
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
void main()
runApp(new MyApp());
class MyApp extends StatelessWidget
@override
Widget build(BuildContext context)
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Flutter Demo Home Page'),
);
class MyHomePage extends StatefulWidget
MyHomePage(Key key, this.title) : super(key: key);
final String title;
@override
_MyHomePageState createState() => new _MyHomePageState();
class _MyHomePageState extends State<MyHomePage>
ScrollController _hideButtonController;
var _isVisible;
@override
initState()
super.initState();
_isVisible = true;
_hideButtonController = new ScrollController();
_hideButtonController.addListener(()
if (_hideButtonController.position.userScrollDirection ==
ScrollDirection.reverse)
if(_isVisible)
setState(()
_isVisible = false;
print("**** $_isVisible up");
);
if (_hideButtonController.position.userScrollDirection ==
ScrollDirection.forward)
if(!_isVisible)
setState(()
_isVisible = true;
print("**** $_isVisible down");
);
);
@override
Widget build(BuildContext context)
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Center(
child: new CustomScrollView(
controller: _hideButtonController,
shrinkWrap: true,
slivers: <Widget>[
new SliverPadding(
padding: const EdgeInsets.all(20.0),
sliver: new SliverList(
delegate: new SliverChildListDelegate(
<Widget>[
const Text('I\'m dedicating every day to you'),
const Text('Domestic life was never quite my style'),
const Text('When you smile, you knock me out, I fall apart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('I realize I am crazy'),
],
),
),
),
],
)),
bottomNavigationBar: AnimatedContainer(
duration: Duration(milliseconds: 500),
height: _isVisible ? 60.0 : 0.0,
child: _isVisible
? new BottomNavigationBar(
type: BottomNavigationBarType.fixed,
items: [
new BottomNavigationBarItem(
icon: Icon(Icons.home),
title: Text('Home'),
),
new BottomNavigationBarItem(
icon: Icon(Icons.card_giftcard),
title: Text('Offers'),
),
new BottomNavigationBarItem(
icon: Icon(Icons.account_box),
title: Text('Account'),
),
],
currentIndex: 0,
)
: Container(
color: Colors.white,
width: MediaQuery.of(context).size.width,
),
),
);
你也可以使用 sliver bar :-
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
void main()
runApp(new MyApp());
class MyApp extends StatelessWidget
@override
Widget build(BuildContext context)
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Flutter Demo Home Page'),
);
class MyHomePage extends StatefulWidget
MyHomePage(Key key, this.title) : super(key: key);
final String title;
@override
_MyHomePageState createState() => new _MyHomePageState();
class _MyHomePageState extends State<MyHomePage>
ScrollController _hideButtonController;
var _isVisible;
@override
initState()
super.initState();
_isVisible = true;
_hideButtonController = new ScrollController();
_hideButtonController.addListener(()
if (_hideButtonController.position.userScrollDirection ==
ScrollDirection.reverse)
setState(()
_isVisible = false;
print("**** $_isVisible up");
);
if (_hideButtonController.position.userScrollDirection ==
ScrollDirection.forward)
setState(()
_isVisible = true;
print("**** $_isVisible down");
);
);
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
TextEditingController searchController = new TextEditingController();
@override
Widget build(BuildContext context)
return Scaffold(
backgroundColor: Colors.white,
resizeToAvoidBottomPadding: true,
drawer: Container(),
key: scaffoldKey,
body: NestedScrollView(
controller: _hideButtonController,
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled)
return <Widget>[
SliverAppBar(
title: Container(
child: Card(
elevation: 3.0,
margin: EdgeInsets.only(top: 10.0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(2.0))),
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 15.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
GestureDetector(
child: Icon(
Icons.sort,
color: Colors.black54,
),
onTap: ()
scaffoldKey.currentState.openDrawer();
,
),
SizedBox(
width: 10.0,
),
Expanded(
child: TextField(
controller: searchController,
decoration: InputDecoration(
border: InputBorder.none,
hintText: "What are you looking for?"),
),
),
GestureDetector(
onTap: ()
searchController.clear();
,
child: Icon(
Icons.clear,
color: Colors.black54,
),
),
],
),
),
),
),
elevation: 10.0,
automaticallyImplyLeading: false,
expandedHeight: 70,
floating: true,
snap: true,
)
];
,
body: new ListView(
children: <Widget>[
const Text('I\'m dedicating every day to you'),
const Text('Domestic life was never quite my style'),
const Text('When you smile, you knock me out, I fall apart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('I realize I am crazy'),
const Text('I\'m dedicating every day to you'),
const Text('Domestic life was never quite my style'),
const Text('When you smile, you knock me out, I fall apart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('And I thought I was so smart'),
const Text('I realize I am crazy'),
],
),
),
bottomNavigationBar: AnimatedContainer(
duration: Duration(seconds: 1),
height: _isVisible ? 60.0 : 0.0,
child: _isVisible
? AnimatedContainer(
duration: Duration(milliseconds: 200),
height: _isVisible ? 60.0 : 0.0,
child: _isVisible
? new BottomNavigationBar(
type: BottomNavigationBarType.fixed,
items: [
new BottomNavigationBarItem(
icon: Icon(Icons.home),
title: Text('Home'),
),
new BottomNavigationBarItem(
icon: Icon(Icons.card_giftcard),
title: Text('Offers'),
),
new BottomNavigationBarItem(
icon: Icon(Icons.account_box),
title: Text('Account'),
),
],
currentIndex: 0,
)
: Container(
color: Colors.white,
width: MediaQuery.of(context).size.width,
),
)
: Container(
color: Theme.of(context).primaryColor,
width: MediaQuery.of(context).size.width,
),
),
// _isVisible
// ? bottomNavigationBar()
// : Container(
// height: 0.0,
// width: MediaQuery.of(context).size.width,
// ),
);
请评论您对此代码的看法,以便我们改进此代码。
这是取自这个答案:- Flutter - Hiding FloatingActionButton
【讨论】:
你知道如何实现隐藏/再现动画吗? 试过了,不幸的是“A RenderFlex 在底部溢出了 39 个像素”。滚动时。 它工作了,但它有滚动故障,滚动不流畅。【参考方案2】:尝试将 ListView 包装为 NotificationListener 的子级并监听滚动事件 https://docs.flutter.io/flutter/widgets/OverscrollNotification-class.html
其他方法是使用 ScrollUpdateNotification https://docs.flutter.io/flutter/widgets/ScrollUpdateNotification-class.html
【讨论】:
【参考方案3】:您需要一个 ScrollController 来监视/观察 Listview 的滚动方向。控制器将在 initState 中初始化,并且应该添加一个监听器......监听器应该根据滚动方向切换一个布尔值......然后底部 Naigatio Bar 应该用 OffStage 包装
这段代码应该有帮助
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
void main()
runApp(MyApp());
class MyApp extends StatelessWidget
// This widget is the root of your application.
@override
Widget build(BuildContext context)
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
class MyHomePage extends StatefulWidget
@override
_MyHomePageState createState() => _MyHomePageState();
class _MyHomePageState extends State<MyHomePage>
bool _isVisible = true;
ScrollController controller;
@override
void initState()
super.initState();
controller = ScrollController();
controller.addListener(()
setState(()
_isVisible = controller.position.userScrollDirection == ScrollDirection.forward;
);
);
@override
Widget build(BuildContext context)
return Scaffold(
body: ListView(
controller: controller,
children: List.generate(200, (index) => Text(("$index"))),
),
bottomNavigationBar: Offstage(
offstage: !_isVisible,
child: BottomNavigationBar(
items: [
BottomNavigationBarItem(
title: Text("Hello"),
icon: Icon(Icons.style)
),
BottomNavigationBarItem(
title: Text("Hi"),
icon: Icon(Icons.style)
),
BottomNavigationBarItem(
title: Text("Hey"),
icon: Icon(Icons.style)
)
],
),
),
);
【讨论】:
你不应该在这个解决方案中使用后台,因为它在处理方面并不便宜。它也没有提供任何动画。【参考方案4】:屏幕截图(Null 安全):
代码:
使用的小部件是StatelessWidget
,所以不用担心会多次调用setState
。
创建此类:
class ScrollListener extends ChangeNotifier
double bottom = 0;
double _last = 0;
ScrollListener.initialise(ScrollController controller, [double height = 56])
controller.addListener(()
final current = controller.offset;
bottom += _last - current;
if (bottom <= -height) bottom = -height;
if (bottom >= 0) bottom = 0;
_last = current;
if (bottom <= 0 && bottom >= -height) notifyListeners();
);
用法:
class MyPage extends StatelessWidget
final ScrollController _controller = ScrollController();
final double _bottomNavBarHeight = 56;
late final ScrollListener _model;
MyPage()
_model = ScrollListener.initialise(_controller);
@override
Widget build(BuildContext context)
return Scaffold(
body: AnimatedBuilder(
animation: _model,
builder: (context, child)
return Stack(
children: [
ListView.builder(
controller: _controller,
itemCount: 20,
itemBuilder: (_, i) => ListTile(title: Text('Item $i')),
),
Positioned(
left: 0,
right: 0,
bottom: _model.bottom,
child: _bottomNavBar,
),
],
);
,
),
);
Widget get _bottomNavBar
return SizedBox(
height: _bottomNavBarHeight,
child: BottomNavigationBar(
backgroundColor: Colors.amber[800],
items: [
BottomNavigationBarItem(icon: Icon(Icons.call), label: 'Call'),
BottomNavigationBarItem(icon: Icon(Icons.message), label: 'Message'),
],
),
);
【讨论】:
【参考方案5】:查看这个答案,=> Bottom Navigation Scrolling 它使用动画来隐藏底部导航栏。您还可以自定义动画。
【讨论】:
以上是关于在 Flutter 中的 Scroll 上隐藏底部导航栏的主要内容,如果未能解决你的问题,请参考以下文章
在 Flutter 应用程序中的 ListView 滚动上隐藏/关闭键盘
如何在 Flutter 中隐藏 TextField 底部的字母计数器
Swift:在 UIWebview Scroll 上隐藏 UIStackView