Flutter Flatter:OrientionBuilder-重用子部件而不重建?
我正在使用方向生成器定义纵向和横向布局。布局包括两个小部件,例如:TextField小部件和GoogleMap小部件。在“纵向”中,布局使用TabBarView在两个小部件之间水平移动。在“横向”中,小部件并排放置在屏幕上的扩展容器中 如果我更新纵向中的文本字段并更改为横向,数据将丢失。我可以用一个变量来管理它,这很快也很简单。但是,如果我重建地图,它可能已经移动,并添加了数百个标记和线条等,我必须在每次用户更改设备方向时重新绘制每个标记。虽然这是可以实现的,但当存在数百个标记和线条时,重新绘制需要相当长的时间 问题是,是否有可能在方向更改过程中重用小部件,包括用户添加的任何标记、线条等,而无需每次重新构建?Ie类似于我们用于TabBar切换的AutomaticEpaLiveClientMixin?还是我处理这个问题的方法不对 范例Flutter Flatter:OrientionBuilder-重用子部件而不重建?,flutter,widget,reusability,device-orientation,Flutter,Widget,Reusability,Device Orientation,我正在使用方向生成器定义纵向和横向布局。布局包括两个小部件,例如:TextField小部件和GoogleMap小部件。在“纵向”中,布局使用TabBarView在两个小部件之间水平移动。在“横向”中,小部件并排放置在屏幕上的扩展容器中 如果我更新纵向中的文本字段并更改为横向,数据将丢失。我可以用一个变量来管理它,这很快也很简单。但是,如果我重建地图,它可能已经移动,并添加了数百个标记和线条等,我必须在每次用户更改设备方向时重新绘制每个标记。虽然这是可以实现的,但当存在数百个标记和线条时,重新绘制
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,
),
);
}
}
类测试扩展StatefulWidget{
Test({Key}):super(Key:Key);
@凌驾
TestState createState()=>TestState();
}
类TestState扩展了状态{
TestState({Key});
小部件mMap;
多行文字;
@凌驾
void initState(){
mMap=gMap();
mText=gText();
super.initState();
}
@凌驾
小部件构建(构建上下文){
返回方向生成器(
生成器:(上下文、方向){
返回方向==方向。纵向
?平面布置图()
:景观布局();
},
);
}
控件布局(){
返回脚手架(
正文:DefaultTabController(
长度:2,
子项:选项卡视图(
//物理学:NeverscrollableScroll物理学(),
儿童:[
gText(),
gMap(),
]
),
),
);
}
Widget landscapeLayout(){
返回脚手架(
正文:世界其他地区(
儿童:[
扩大(
子项:gText(),
),
扩大(
儿童:gMap()
),
],
),
);
}
TextField gText(){
返回TextField();
}
谷歌地图gMap(){
返回谷歌地图(
mapType:mapType.hybrid,
initialCameraPosition:CameraPosition(
目标:LatLng(37.0,-122.0),
缩放:2,
),
);
}
}
经过大量努力和测试多个选项后,我得出结论,orientation builder中的两个布局是完全独立的,两个布局永远不会相遇。作为这种特殊情况下的一种解决方法,我放弃了方向生成器,而是创建了一行,其中包含两个宽度均为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()),
)
]
),
);
}
@覆盖
小部件构建(构建上下文){
if(MediaQuery.of(context.orientation==orientation.scape){
formFlex=1;
mapFlex=1;
}
else if(MediaQuery.of(context.orientation==orientation.taritary&&formFlex==mapFlex){
formFlex=1;
mapFlex=0;
}
返回脚手架(
appBar:getAppBar(),
正文:世界其他地区(
儿童:[
扩大(
flex:formFlex,
子:容器(宽度:0,子:文本('Test1')),
),
扩大(
flex:mapFlex,
子:容器(宽度:0,子:gMap()),
)
]
),
);
}