【问题标题】:Flutter: OrientationBuilder - reuse child widgets without rebuilding?Flutter:OrientationBuilder - 重用子小部件而不重建?
【发布时间】:2020-03-14 13:21:58
【问题描述】:

我正在使用 OrientationBuilder 来定义纵向和横向布局。布局包括两个小部件,例如:TextField 小部件和 GoogleMap 小部件。在“纵向”中,布局利用 TabBarView 在两个小部件之间水平移动。在“横向”中,小部件在扩展容器中并排放置在屏幕上。

如果我将 TextField 更新为纵向并更改为横向,则数据将丢失。我可以用一个变量来管理它,这既快速又简单。但是,如果我重建可能已经移动并添加了数百个标记和线条等的地图,我必须在每次用户更改设备方向时重新绘制每个标记。虽然这是可以实现的,但当存在数百个标记和线条时,重绘需要相当长的时间。

那么问题是,是否可以在方向更改中重复使用小部件,包括任何用户添加的标记、线条等,而无需每次都重新构建?即类似于我们用于 TabBar 班次的 AutomaticKeepAliveClientMixin 的东西?还是我处理的方式不对?

例子

class Test extends StatefulWidget {
  Test ({Key key}) : super(key: key);

  @override
  TestState createState() => TestState();
}

class TestState extends State<Test > {
  TestState({Key key});
  Widget mMap;
  Widget mText;

  @override
  void initState() {
    mMap = gMap();
    mText = gText();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return OrientationBuilder(
      builder: (context, orientation) {
        return orientation == Orientation.portrait
            ? portraitLayout()
            : landscapeLayout();
      },
    );
  }

  Widget portraitLayout() {
    return Scaffold(
      body: DefaultTabController(
        length: 2,
        child: TabBarView(
            //physics: NeverScrollableScrollPhysics(),
            children: <Widget>[
              gText(),
              gMap(),
            ]
        ),
      ),
    );
  }

  Widget landscapeLayout() {
    return Scaffold(
      body: Row(
        children: <Widget>[
          Expanded(
            child: gText(),
          ),
          Expanded(
              child: gMap()
          ),
        ],
      ),
    );
  }

  TextField gText() {
    return TextField();
  }

  GoogleMap gMap() {
    return GoogleMap(
      mapType: MapType.hybrid,
      initialCameraPosition: CameraPosition(
        target: LatLng(37.0, -122.0),
        zoom: 2,
      ),
    );
  }
}

【问题讨论】:

    标签: flutter widget reusability device-orientation


    【解决方案1】:

    经过大量努力和测试多个选项后,我得出结论,方向构建器中的两种布局是完全独立的,两者永远不会相遇。作为这种特殊情况下的解决方法,然后我丢弃了方向构建器,而是创建了一个包含两个宽度均为 0 的扩展小部件的行,并根据设备方向更新了 flex。例如,在纵向,1(显示)和 0(隐藏)的 flex 中,浮动操作栏可以根据需要进行反转,而在横向 1 和 1 的 flex 中,可以平等地显示两者。可能不是正确的方法,但它很简单,并且有一天其他人可能会感兴趣。

    @override
      Widget build(BuildContext context) {
        if (MediaQuery.of(context).orientation == Orientation.landscape) {
          formFlex = 1;
          mapFlex = 1;
        }
        else if (MediaQuery.of(context).orientation == Orientation.portrait && formFlex==mapFlex){
          formFlex = 1;
          mapFlex = 0;
        }
    
        return Scaffold(
          appBar: getAppBar(),
          body: Row(
              children: <Widget>[
                Expanded(
                  flex:formFlex,
                  child: Container(width: 0, child: Text('Test1')),
                ),
                Expanded(
                  flex:mapFlex,
                  child: Container(width: 0, child: gMap()),
                )
              ]
          ),
        );
      }
    

    【讨论】:

      猜你喜欢
      • 2019-01-14
      • 1970-01-01
      • 2021-03-03
      • 2021-12-31
      • 2021-09-19
      • 2020-07-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多