JWR*_*ich 1 android dart flutter
我有一个包含a listView和a 的父对象,floatingActionButton我想floatingActionButton在用户开始滚动时隐藏,我设法在父窗口小部件中做到这一点,但这需要每次重新构建列表。
我已经将其floatingActionButton移至单独的类,因此我可以更新状态并仅重建该小部件,因为我遇到的问题是将数据从ScrollController父类中的数据传递给孩子,这在通过导航进行操作时很简单,但是接缝却更多笨拙而不重建父母!
bof*_*mer 13
为了获得最佳性能,您可以创建自己的包装器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,
);
}
}
Run Code Online (Sandbox Code Playgroud)
或者,您也可以为 创build一个包装器FloatingActionButton,但这可能会破坏过渡。
I think using a stream is more simpler and also pretty easy.
You just need to post to the stream when your event arrives and then use a stream builder to respond to those changes.
Here I am showing/hiding a component based on the focus of a widget in the widget hierarchy.
I've used the rxdart package here but I don't believe you need to. also you may want to anyway because most people will be using the BloC pattern anyway.
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();
}),
)
],
),
);
}
}
Run Code Online (Sandbox Code Playgroud)
当父级中的值发生变化时,一种仅重建子级小部件的好方法是使用ValueNotifier和ValueListenableBuilder。将 的实例添加ValueNotifier到父级的状态类,并将要重建的小部件包装在ValueListenableBuilder.
当您想要更改该值时,请使用通知程序而不调用,setState然后使用新值重建子小部件。
import 'package:flutter/material.dart';
class Parent extends StatefulWidget {
@override
_ParentState createState() => _ParentState();
}
class _ParentState extends State<Parent> {
ValueNotifier<bool> _notifier = ValueNotifier(false);
@override
Widget build(BuildContext context) {
return Column(
children: [
ElevatedButton(onPressed: () => _notifier.value = !_notifier.value, child: Text('toggle')),
ValueListenableBuilder(
valueListenable: _notifier,
builder: (BuildContext context, bool val, Widget child) {
return Text(val.toString());
}),
],
);
}
@override
void dispose() {
_notifier.dispose();
super.dispose();
}
}
Run Code Online (Sandbox Code Playgroud)
您可以使用StatefulBuilder并使用其 setState 函数在其下构建小部件。
例子:
import 'package:flutter/material.dart';
class MyWidget extends StatefulWidget {
@override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
int count = 0;
@override
Widget build(BuildContext context) {
return Column(
children: [
// put widget here that you do not want to update using _setState of StatefulBuilder
Container(
child: Text("I am static"),
),
StatefulBuilder(builder: (_context, _setState) {
// put widges here that you want to update using _setState
return Column(
children: [
Container(
child: Text("I am updated for $count times"),
),
RaisedButton(
child: Text('Update'),
onPressed: () {
// Following only updates widgets under StatefulBuilder as we are using _setState
// that belong to StatefulBuilder
_setState(() {
count++;
});
})
],
);
}),
],
);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6226 次 |
| 最近记录: |