Flutter:OrientationBuilder-重用子小部件而无需重建吗?

时间:2019-11-19 05:06:21

标签: flutter widget reusability device-orientation

我正在使用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,
      ),
    );
  }
}

1 个答案:

答案 0 :(得分:0)

经过大量的努力并测试了多个选项,我得出的结论是方向生成器中的两个布局完全分开,并且永远不会相遇。作为这种情况下的解决方法,我放弃了方向生成器,而是创建了一个行,其中包含两个宽度均为0的扩展小部件,并根据设备方向更新了flex。例如,在纵向模式下,弯曲度为1(显示)和0(隐藏),并说有一个浮动动作条,可根据需要反转;在横向模式中,弯曲度为1和1可均等显示。可能不是正确的方法,而是简单的方法,有一天可能会引起其他人的兴趣。

@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()),
            )
          ]
      ),
    );
  }