Flutter set子窗口小部件,不重建父窗口

问题描述 投票:0回答:2

我有一个包含listViewfloatingActionButton的父级我想在用户开始滚动时隐藏floatingActionButton我已设法在父窗口小部件中执行此操作但这需要每次重建列表。

我已经将floatingActionButton移动到一个单独的类,所以我可以更新状态,只重建该小部件我遇到的问题是将数据从父类中的ScrollController传递给子节点这很简单,当通过导航这样做但接缝时但没有重建父母就更尴尬!

android dart flutter
2个回答
0
投票

为了获得最佳性能,您可以在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创建一个包装器,但这可能会破坏转换。


2
投票

我认为使用流更简单也很容易。

您只需在事件到达时发布到流,然后使用流构建器来响应这些更改。

在这里,我基于窗口小部件层次结构中窗口小部件的焦点显示/隐藏组件。

我在这里使用过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();
            }),
          )
        ],
      ),
    );
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.