Как перестроить виджеты Flutter при изменении размера устройства в режиме выпуска для Flutter View в приложении Android? - PullRequest
0 голосов
/ 18 декабря 2018

Обновление: я попробовал это с обычным приложением 100% Flutter и не смог его воспроизвести.Тем не менее, в приложении Flutter View для Android-приложения я записал размер, и есть журнал, где он равен 0x0.Таким образом, кажется, что приведенный ниже вопрос применим только в этом случае.


У меня есть виджет, который находит размер устройства и соответственно строит виджет.Я использовал LayoutBuilder (и constraints.biggest) для этого изначально в функции build (), а также попытался использовать MediaQuery.of (context).Виджет является StatelessWidget.Я не думаю, что это должно быть Stateful, так как я не изменяю его состояние (хотя размер устройства меняется) и в режиме отладки виджеты рисуются правильно.

Отладка: debug Релиз: release

Код 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-приложение для:

  1. Сверните этот пример: https://github.com/flutter/flutter/tree/master/examples/flutter_view
  2. Замените 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

Ответы [ 2 ]

0 голосов
/ 07 февраля 2019

Я решил эту проблему, получив размер только в StatefulWidget.Таким образом, я получаю уведомление об изменении размера устройства и перерисовывании всех его дочерних StatelessWidgets.Я также проверил, если размер устройства в StatefulWidget равен 0x0, просто верните контейнер.По какой-то причине, если я возвращаю RandomContainer (), он не будет перестроен позже, когда размер устройства изменился.

0 голосов
/ 18 декабря 2018

Это небольшая разница во времени между режимом выпуска и отладки.Вероятно, потому что в режиме выпуска приложение запускается быстрее, и системе требуется некоторое время для предоставления размера.

Таким образом, в режиме выпуска вы сначала получаете 0, 0, а через некоторое время оно обновляется до фактического размера.,Все, что вам нужно сделать, это убедиться, что код не вызывает исключение, когда размер 0, 0.Например, верните пустой контейнер или аналогичный.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...