更新:我用一个普通的 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 的完整构建代码是:
- 拉下这个例子: 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),
),
);
}
}
在调试模式下,小部件正确绘制,但在发布模式下,小部件的大小为 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 行会重复(重绘),但事实并非如此。
为了比较,这是它在调试模式下的样子。它完全绕过了 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