子窗口小部件的Flutter setState无需重建父窗口 [英] Flutter setState of child widget without rebuilding parent

查看:153
本文介绍了子窗口小部件的Flutter setState无需重建父窗口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含 listView floatingActionButton 的父级,我想在用户开始滚动时隐藏 floatingActionButton 要在父窗口小部件中执行此操作,但这需要每次都重新构建列表.

I have a parent that contain a listView and a floatingActionButton i would like to hide the floatingActionButton when the user starts scrolling i have managed to do this within the parent widget but this requires the list to be rebuilt each time.

我将 floatingActionButton 移到了单独的类,因此我可以更新状态并仅重建该小部件,因为我遇到的问题是从 ScrollController 中传递数据子类的父类,这在通过导航进行操作时很简单,但在不重建父类的情况下却缝得很尴尬!

I have moved the floatingActionButton to a separate class so i can update the state and only rebuild that widget the problem i am having is passing the data from the ScrollController in the parent class to the child this is simple when doing it through navigation but seams a but more awkward without rebuilding the parent!

推荐答案

为获得最佳性能,您可以围绕 Scaffold 创建自己的包装,该包装将 body 作为参数.在 HideFabOnScrollScaffoldState 中调用 setState 时,不会重新构建 body 小部件.

For optimal performance, you can create your own wrapper around Scaffold that gets the body as a parameter. The body widget will not be rebuilt when setState is called in HideFabOnScrollScaffoldState.

这是一种常见模式,也可以在诸如 AnimationBuilder 之类的核心小部件中找到.

This is a common pattern that can also be found in core widgets such as 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 创建包装器,但这可能会中断过渡.

Alternatively you could also create a wrapper for FloatingActionButton, but that will probably break the transition.

这篇关于子窗口小部件的Flutter setState无需重建父窗口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆