簡體   English   中英

Flutter:OrientationBuilder - 重用子小部件而不重建?

[英]Flutter: OrientationBuilder - reuse child widgets without rebuilding?

我正在使用 OrientationBuilder 來定義縱向和橫向布局。 布局包括兩個小部件,例如:TextField 小部件和 GoogleMap 小部件。 在“縱向”中,布局利用 TabBarView 在兩個小部件之間水平移動。 在“橫向”中,小部件並排放置在擴展容器中的屏幕上。

如果我以縱向更新 TextField 並更改為橫向,則數據將丟失。 我可以用一個變量來管理它,這既快速又簡單。 但是,如果我重建 Map 可能已經移動並添加了數百個標記和線條等,我必須在每次用戶更改設備方向時重新繪制每個標記。 雖然這是可以實現的,但當存在數百個標記和線條時,重繪需要相當長的時間。

那么問題是,是否可以在方向更改中重用小部件,包括任何用戶添加的標記、線條等,而無需每次都重新構建? 即類似於我們用於 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,
      ),
    );
  }
}

經過大量努力和測試多個選項后,我得出結論,方向構建器中的兩種布局是完全獨立的,兩者永遠不會相遇。 作為這種特殊情況下的解決方法,我放棄了方向構建器,而是創建了一個包含兩個寬度均為 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()),
            )
          ]
      ),
    );
  }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM