Обновление: я попробовал это с обычным приложением 100% Flutter и не смог его воспроизвести.Тем не менее, в приложении Flutter View для Android-приложения я записал размер, и есть журнал, где он равен 0x0.Таким образом, кажется, что приведенный ниже вопрос применим только в этом случае.
У меня есть виджет, который находит размер устройства и соответственно строит виджет.Я использовал LayoutBuilder (и constraints.biggest) для этого изначально в функции build (), а также попытался использовать MediaQuery.of (context).Виджет является StatelessWidget.Я не думаю, что это должно быть Stateful, так как я не изменяю его состояние (хотя размер устройства меняется) и в режиме отладки виджеты рисуются правильно.
Отладка: Релиз:
Код 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-приложение для:
- Сверните этот пример: 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