更新:我使用常规 100% Flutter 应用程序尝试了此操作,但无法复制它。不过,在 Android 应用程序的 Flutter View 中,我记录了大小,并且有一个日志,其中它是 0x0。所以看来下面的问题只适用于这种情况。
我有一个小部件,可以查找设备的大小并相应地构建一个小部件。我最初在 build() 函数中使用 LayoutBuilder (和constraints.biggest),并且还尝试使用 MediaQuery.of(context)。该小部件是一个 StatelessWidget。我认为它不应该是有状态的,因为我不会更改它的状态(尽管设备大小发生变化)并且在 Debug模式下小部件会正确绘制。
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 的完整构建代码是:
- 下拉此示例: https://github.com/flutter/flutter/tree/master/examples/flutter_view
- 将 main.dart 替换为(我知道这很乱):
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),
),
);
}
}
在 Debug模式下,小部件可以正确绘制,但在 Release模式下,小部件的大小为 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)
我本来希望中间的 3 条线会重复(重画),但它们没有。
为了进行比较,这是 Debug模式下的样子。它完全绕过了 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
最佳答案
这是 Release模式和 Debug模式之间的一点时间差异。可能是因为在 Release模式下应用程序启动速度更快,并且系统需要一些时间来提供大小。
因此,在 Release模式下,您首先会得到 0, 0
,不久之后它就会更新为实际大小。您需要做的就是确保当大小为 0, 0
时代码不会引发异常。例如返回一个空容器或类似容器。
关于android - Android 应用程序中 Flutter View 的 Release模式下,当设备尺寸发生变化时,如何重建 Flutter 小部件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53838043/