更新:我使用常规的100%Flutter应用程序尝试了此操作,但无法复制它。但是,在Android应用程序的Flutter View中,我记录了大小,并在日志中记录了0x0。因此,似乎以下问题仅在这种情况下适用。
我有一个小部件,可以找到设备的大小并相应地构建一个小部件。最初,我在build()函数中使用LayoutBuilder(和constraints.biggest),并尝试使用MediaQuery.of(context)。该小部件是一个StatelessWidget。我不认为它应该是有状态的,因为我不会更改它的状态(尽管设备大小会发生变化),并且在调试模式下小部件可以正确绘制。
build()代码本质上是:
final size = MediaQuery.of(context).size;
return Stack(
children: [
Container(width: 200),
Container(width: size.width - _padding),
Container(width: size.width - _morePadding),
],
);
更新:Flutter-View-in-Android-app的完整构建代码为:
import 'dart:async';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() {
runApp(FlutterView());
}
class FlutterView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter View',
theme: ThemeData(
primarySwatch: Colors.grey,
),
home: RandomContainer(),
);
}
}
class RandomContainer extends StatelessWidget {
@override
Widget build(BuildContext context) {
final Size size = MediaQuery.of(context).size;
print('maryx $size');
return MyHomePage(
title: 'Flutter Demo Home Page',
width: size.width,
height: size.height,
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({
Key key,
this.title,
this.width,
this.height,
}) : super(key: key);
final String title;
final double width;
final double height;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
static const String _channel = 'increment';
static const String _pong = 'pong';
static const String _emptyMessage = '';
static const BasicMessageChannel<String> platform =
BasicMessageChannel<String>(_channel, StringCodec());
int _counter = 0;
Widget _image = Container();
@override
void initState() {
super.initState();
platform.setMessageHandler(_handlePlatformIncrement);
_buildImage();
}
Future<String> _handlePlatformIncrement(String message) async {
setState(() {
_counter++;
});
return _emptyMessage;
}
void _sendFlutterIncrement() {
platform.send(_pong);
}
Widget _buildWidgets() {
final size = MediaQuery.of(context).size;
return Stack(
children: [
Center(
child: Container(
width: size.width - 50.0,
height: 100.0,
color: Colors.pink[900],
),
),
Center(
child: _image,
),
Center(
child: Container(
width: 100.0,
height: 50.0,
color: Colors.pink[200],
)),
],
);
}
Future<void> _buildImage() async {
final recorder = ui.PictureRecorder();
final canvas = ui.Canvas(recorder);
final rrect = ui.RRect.fromRectAndRadius(
ui.Rect.fromLTWH(0.0, 0.0, widget.width, 100.0),
Radius.circular(widget.width / 2));
canvas.drawRRect(rrect, ui.Paint()..color = Colors.pink[500]);
// Save drawing into a png.
final picture = recorder.endRecording();
final image = picture.toImage(widget.width.toInt(), 100);
final pngBytes = await image.toByteData(format: ui.ImageByteFormat.png);
// See https://github.com/flutter/flutter/issues/6246
if (!mounted) return;
// Save png as an Image widget.
setState(() {
_image = Image.memory(
pngBytes.buffer.asUint8List(),
height: 100,
width: widget.width,
fit: BoxFit.cover,
);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Expanded(
child: Center(
child: Text(
'Platform button tapped $_counter time${_counter == 1 ? '' : 's'}.',
style: const TextStyle(fontSize: 17.0))),
),
_buildWidgets(),
Container(
padding: const EdgeInsets.only(bottom: 15.0, left: 5.0),
child: Row(
children: <Widget>[
Image.asset('assets/flutter-mark-square-64.png', scale: 1.5),
const Text('Flutter', style: TextStyle(fontSize: 30.0)),
],
),
),
],
),
floatingActionButton: FloatingActionButton(
onPressed: _sendFlutterIncrement,
child: const Icon(Icons.add),
),
);
}
}
在调试模式下,小部件可以正确绘制,但是在发布模式下,小部件的大小为0x0,因为在绘制时,设备的大小为0x0。这似乎与以下内容有关:https://github.com/flutter/flutter/issues/11697
如何更改尺寸更改后重新绘制小部件?假设LayoutBuilder和MediaQuery 都应该告诉窗口小部件重新绘制,并且当我添加打印语句时,设备大小正在改变:
12-18 12:01:31.084 1587 1752 I flutter : device: Size(0.0, 0.0)
12-18 12:01:31.087 1587 1752 I flutter : length 200.0 // hardcoded widget, used as a control (does not depend on device size)
12-18 12:01:31.088 1587 1752 I flutter : length 0.0 // widget based on device size
12-18 12:01:31.089 1587 1752 I flutter : length 0.0 // widget based on device size
12-18 12:01:31.563 1587 1752 I flutter : device: Size(600.0, 400.0)
我希望中间的三行重复(重画),但不会。
为了进行比较,这是在调试模式下的样子。它完全绕过了0x0设备尺寸:
12-18 12:10:44.506 1897 2063 I flutter : device: Size(600.0, 400.0)
12-18 12:10:44.593 1897 2063 I flutter : length 200.0
12-18 12:10:44.627 1897 2063 I flutter : length 563.3333333333334
12-18 12:10:44.631 1897 2063 I flutter : length 333.3333333333334
答案 0 :(得分:0)
这与发布和调试模式之间的时间差异有些关系。可能是因为在发布模式下,该应用的启动速度更快,并且系统需要一些时间来提供大小。
因此,在发布模式下,您首先会获得0, 0
,不久后它就会更新为实际大小。您需要做的就是确保大小为0, 0
时代码不会引起异常。例如,返回一个空的Container或类似容器。
答案 1 :(得分:0)
我最终只通过在StatefulWidget中检索大小来解决了这个问题。这样,当设备大小更改且其所有子StatelessWidgets被重绘时,我会收到通知。我也做了检查,如果StatefulWidget中的设备大小为0x0,则只返回一个Container。由于某种原因,如果我返回RandomContainer(),则在设备大小更改后,以后将无法重建它。