更新: 通常の 100% Flutter アプリでこれを試しましたが、複製できませんでした。ただし、Android アプリの Flutter View では、サイズをログに記録すると、0x0 のログがあります。したがって、以下の質問はこの場合にのみ適用されるようです。
デバイスのサイズを検出し、それに応じてウィジェットを構築するウィジェットがあります。これには、最初は build() 関数で LayoutBuilder (および constraint.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 アプリの完全なビルド コードは次のとおりです。
- この例をプルダウン: 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 の両方がウィジェットに再描画を指示する必要があり、print ステートメントを追加すると、デバイスのサイズが変化します。
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