基本上,我想渲染一个ModalRoute
,它依赖于其下面路由中的某些小部件。
要实现此目的,我使用的是GlobalKey
,我将其附加到较低路径的小部件上:
/// in LOWER route (widget that is in lower route)
@override
Widget build(BuildContext context) {
return Container(
key: globalKey,
child: ..,
);
}
/// UPPER route (different class!)
/// called using a function on tap in the lower route widget
/// `showModalRoute(globalKey)`
@override
Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
final renderBox = globalKey.currentContext.findRenderObject() as RenderBox;
final Size size = renderBox.size;
return SizedBox(
width: size.width,
height: size.height,
child: ..,
);
}
我正在尝试使其对方向更改做出响应。方向更改时,下部路径中的小部件会更改大小。
这里的问题是上方路线似乎是在下方路线之前建造的。也许不是这种情况,但是 size
始终是以前的尺寸,即旋转到potrait或反之亦然时得到的景观尺寸,就好像上面的路线是在较低的路线(我的假设)。职位也是如此。我基本上得到了上一个RenderBox
。
我是否可以通过renderBox.localToGlobal(0, 0)
来获取小部件的当前位置?我想我可以通过在buildPage
具有新大小之后呈现 GlobalKey
来实现此目的。
答案 0 :(得分:1)
检查此代码,告诉我它是否按预期工作
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
void main() => runApp(MyApp());
StreamController<MyWidgetStatus> firstRouteStatus =
StreamController.broadcast();
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Orination Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with WidgetsBindingObserver {
GlobalKey _stateKey;
MyWidgetStatus _status;
double height;
double width;
@override
void initState() {
WidgetsBinding.instance.addObserver(this);
_stateKey = GlobalKey();
SchedulerBinding.instance.addPostFrameCallback(_calculatePositionOffset);
super.initState();
}
_calculatePositionOffset(_) {
_status = _getPositions(_stateKey);
firstRouteStatus.add(_status);
print("position = ${_status.position}");
}
MyWidgetStatus _getPositions(_key) {
final RenderBox renderBoxRed = _key.currentContext.findRenderObject();
final position = renderBoxRed.localToGlobal(Offset.zero);
final height = renderBoxRed.constraints.maxHeight;
final width = renderBoxRed.constraints.maxWidth;
return MyWidgetStatus(position: position, width: width, hight: height);
}
void didChangeMetrics() {
print("Metrics changed");
SchedulerBinding.instance.addPostFrameCallback(_calculatePositionOffset);
super.didChangeMetrics();
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
child: Icon(Icons.navigate_next),
onPressed: () {
_settingModalBottomSheet(context);
}),
body: OrientationBuilder(
builder: (context, orientation) {
return Center(
child: LayoutBuilder(
builder: (context, constraints) => SizedBox(
key: _stateKey,
height: orientation == Orientation.portrait ? 100.0 : 50,
width: orientation == Orientation.portrait ? 50.0 : 100.0,
child: Container(
color: Colors.red,
),
),
),
);
},
),
);
}
void _settingModalBottomSheet(context) {
showModalBottomSheet(
context: context,
builder: (BuildContext bc) {
return Scaffold(
body: StreamBuilder(
stream: firstRouteStatus.stream,
builder: (context, AsyncSnapshot<MyWidgetStatus> snapshot) =>
snapshot.hasData
? Container(
child: Text("Position = ${snapshot.data.position}"),
)
: Text("No Data"),
),
);
});
}
}
class MyWidgetStatus {
final Offset position;
final double hight;
final double width;
MyWidgetStatus({
this.position,
this.hight,
this.width,
});
}
编辑:如果您需要在开始时呈现信息,则可以使用BehaviorSubject而不是像本机StreamController这样的
import 'package:rxdart/rxdart.dart';
StreamController<MyWidgetStatus> firstRouteStatus =
BehaviorSubject();
在编写此行时,还必须在pubspec.yaml中添加RxDart包,它是0.22.0。
rxdart: ^0.22.0