我有一个包含listView
和floatingActionButton
的父级我想在用户开始滚动时隐藏floatingActionButton
我已设法在父窗口小部件中执行此操作但这需要每次重建列表。
我已经将floatingActionButton
移动到一个单独的类,所以我可以更新状态,只重建该小部件我遇到的问题是将数据从父类中的ScrollController
传递给子节点这很简单,当通过导航这样做但接缝时但没有重建父母就更尴尬!
为了获得最佳性能,您可以在Scaffold
周围创建自己的包装器,将body
作为参数。在body
中调用setState
时,不会重建HideFabOnScrollScaffoldState
小部件。
这是一种常见的模式,也可以在核心小部件中找到,例如AnimationBuilder
。
import 'package:flutter/material.dart';
main() => runApp(MaterialApp(home: MyHomePage()));
class MyHomePage extends StatefulWidget {
@override
State<StatefulWidget> createState() => MyHomePageState();
}
class MyHomePageState extends State<MyHomePage> {
ScrollController controller = ScrollController();
@override
Widget build(BuildContext context) {
return HideFabOnScrollScaffold(
body: ListView.builder(
controller: controller,
itemBuilder: (context, i) => ListTile(title: Text('item $i')),
),
floatingActionButton: FloatingActionButton(
onPressed: () {},
child: Icon(Icons.add),
),
controller: controller,
);
}
}
class HideFabOnScrollScaffold extends StatefulWidget {
const HideFabOnScrollScaffold({
Key key,
this.body,
this.floatingActionButton,
this.controller,
}) : super(key: key);
final Widget body;
final Widget floatingActionButton;
final ScrollController controller;
@override
State<StatefulWidget> createState() => HideFabOnScrollScaffoldState();
}
class HideFabOnScrollScaffoldState extends State<HideFabOnScrollScaffold> {
bool _fabVisible = true;
@override
void initState() {
super.initState();
widget.controller.addListener(_updateFabVisible);
}
@override
void dispose() {
widget.controller.removeListener(_updateFabVisible);
super.dispose();
}
void _updateFabVisible() {
final newFabVisible = (widget.controller.offset == 0.0);
if (_fabVisible != newFabVisible) {
setState(() {
_fabVisible = newFabVisible;
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: widget.body,
floatingActionButton: _fabVisible ? widget.floatingActionButton : null,
);
}
}
或者你也可以为FloatingActionButton
创建一个包装器,但这可能会破坏转换。
我认为使用流更简单也很容易。
您只需在事件到达时发布到流,然后使用流构建器来响应这些更改。
在这里,我基于窗口小部件层次结构中窗口小部件的焦点显示/隐藏组件。
我在这里使用过rxdart包,但我认为你不需要。你也可能想要,因为大多数人都会使用BloC模式。
import 'dart:async';
import 'package:rxdart/rxdart.dart';
class _PageState extends State<Page> {
final _focusNode = FocusNode();
final _focusStreamSubject = PublishSubject<bool>();
Stream<bool> get _focusStream => _focusStreamSubject.stream;
@override
void initState() {
super.initState();
_focusNode.addListener(() {
_focusStreamSubject.add(_focusNode.hasFocus);
});
}
@override
void dispose() {
_focusNode.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: <Widget>[
_buildVeryLargeComponent(),
StreamBuilder(
stream: _focusStream,
builder: ((context, AsyncSnapshot<bool> snapshot) {
if (snapshot.hasData && snapshot.data) {
return Text("keyboard has focus")
}
return Container();
}),
)
],
),
);
}
}