Как заставить желтый контейнер расширяться и заполнять остальную часть пространства, доступного его фиолетовым родителям

Это конкретный пример, для которого требуются случаи 2 и 3 из этого другого сообщения Как использовать ограничения и размеры других виджетов на этапе сборки

------------------------- ОСНОВНАЯ НАСЛЕДИЕ ----------------------- -

main [FLEX] дочерний элемент 1: красный (развернутый) дочерний элемент 2: фиолетовый (не раскрывается, но подчиняется ограничению min) [FLEX] ------ дочерний элемент 1: зеленый (не раскрывается, работает должным образом) --- --- ребенок 2: желтый (я хотел бы, чтобы он заполнил остальную часть доступного фиолетового пространства, но система не позволяет мне просто использовать расширенное)

-------------------------ЦЕЛЬ------------------------ -

Я хочу, чтобы желтая рамка заполнила остальное пространство внутри фиолетовой рамки.

ПРИМЕЧАНИЕ: очень специфическая комбинация виджетов, которая не позволяет мне обернуть желтый контейнер в развернутом виджете.

------------------------- ПОЧЕМУ Я НЕ МОГУ ИСПОЛЬЗОВАТЬ РАСШИРЕННЫЙ -------------------- -----

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

в этом конкретном случае у меня есть 2 контейнера внутри гибкого дочернего элемента 1 (основного): красный расширяется, поэтому ... дочерний элемент 2 (основного): фиолетовый пытается сжать обертку своих дочерних элементов и взять наименьшее количество пространство, насколько это возможно, но технически у него нет максимальных ограничений (только минимальные ограничения, поэтому все еще виден фиолетовый)

фиолетовый дочерний элемент также является гибким и имеет 2 дочерних элемента, поскольку фиолетовый гибкий элемент пытается сжать обертку своих дочерних элементов, он скажет своим дочерним элементам сделать тот же дочерний элемент 1 (фиолетовый): зеленый контейнер делает это, и его хорошо, потому что я хочу он должен сделать это, но ... ребенок 2 (фиолетового цвета): я хочу, чтобы желтый контейнер заполнил пространство, созданное фиолетовым, с его параметром min-width

проблема в том, что желтый контейнер, фиолетовый родительский элемент, говорит ему обернуть его дочерние элементы (как объяснено выше), но затем, если я заверну его в расширенный виджет, вы скажете желтому контейнеру расширяться или, другими словами, не сжимать его дочерние элементы .. . и хорошо, что желтый контейнер может как сжимать пленку, так и не сжимать ее дочерние элементы, поэтому вы получите ошибку

Итак ... мне нужно знать расчетную ширину фиолетового контейнера, затем расчетную ширину зеленого контейнера, тогда ширина моего желтого контейнера будет желтой. Width = purple.width - green.width

------------------------- ВЫВОД КОДА ----------------------- -

здесь показан вывод кода ниже

показывает текущий результат по сравнению с желаемым

------------------------- ГЛАВНАЯ ДАР ---------------------- ---

    import 'package:flutter/material.dart';
    import 'materialSheet.dart';

    void main() => runApp(new MyApp());

    class MyApp extends StatelessWidget {
      final appTitle = 'Material Sheets Demo';

      @override
      Widget build(BuildContext context) {
        return new MaterialApp(
          theme: ThemeData.dark(),
          home: new MaterialSheet(
            app: new Text("kill \n\n me plz"),
            sheet: new Icon(Icons.keyboard),
            attachment: new Icon(Icons.attachment),
            position: sheetPosition.right,
            placement: attachmentPlacement.inside,
            sheetMin: 125.0,
          ),
        );
      }
    }

------------------------- ЛИСТ МАТЕРИАЛОВ ---------------------- ---

    import 'package:flutter/material.dart';

//-------------------------Enumerations-------------------------

enum sheetPosition { top, right, bottom, left }
enum sheetType { modal, persistent }
enum attachmentPlacement { inside, outside }

class MaterialSheet extends StatelessWidget {
  //-------------------------Parameters-------------------------

  final Widget app;
  final Widget sheet;
  final Widget attachment;

  final sheetPosition position;
  final sheetType type; //TODO add in the scrim behind the thing
  final attachmentPlacement placement;

  final double sheetMin; //TODO
  final double sheetMax; //TODO
  final double percentBeforeOpen; //TODO
  final bool autoOpenIndicator; //TODO
  final double percentBeforeClose; //TODO
  final bool autoCloseIndicator; //TODO

  final bool vertiScroll; //TODO
  final bool horiScroll; //TODO

  final bool swipeToOpen; //TODO
  final bool swipeToClose; //TODO

  MaterialSheet(
      {@required this.app,
      @required this.sheet,
      this.attachment,
      this.position: sheetPosition.bottom,
      this.type: sheetType.modal,
      this.placement: attachmentPlacement.inside,
      this.sheetMin,
      this.sheetMax,
      this.percentBeforeOpen: .5,
      this.autoOpenIndicator: true,
      this.percentBeforeClose: .5,
      this.autoCloseIndicator: true,
      this.vertiScroll: false,
      this.horiScroll: false,
      this.swipeToOpen: true,
      this.swipeToClose: true});

  //-------------------------Helper Code-------------------------k

  BoxConstraints _calcBoxConstraints(bool fullWidth) {
    if (sheetMin == null && sheetMax == null)
      return new BoxConstraints();
    else {
      if (sheetMin != null && sheetMax != null) {
        if (fullWidth) //we only care for height
          return new BoxConstraints(
            minHeight: sheetMin,
            maxHeight: sheetMax,
          );
        else //we only care for width
          return new BoxConstraints(minWidth: sheetMin, maxWidth: sheetMax);
      } else {
        if (sheetMin != null) {
          //we only have min
          if (fullWidth) //we only care for height
            return new BoxConstraints(minHeight: sheetMin);
          else //we only care for width
            return new BoxConstraints(minWidth: sheetMin);
        } else {
          //we only have max
          if (fullWidth) //we only care for h`eight
            return new BoxConstraints(maxHeight: sheetMax);
          else //we only care for width
            return new BoxConstraints(maxWidth: sheetMax);
        }
      }
    }
  }

  //-------------------------Actual Code-------------------------

  @override
  Widget build(BuildContext context) {

    bool isWidthMax =
        (position == sheetPosition.bottom || position == sheetPosition.top);

    //-----Create the Widgets and Initially calculate Sizes

    print("before test");
    Scaffold testScaff = theSheet(isWidthMax, context);
    print("after test");

    //-----Apply Size constraints as needed

    Align testAl = new Align();

    return new Stack(
      children: <Widget>[
        //---------------Contains your Application
        new Scaffold(
          backgroundColor: Colors.green,
          body: app,
        ),
        //---------------Contains the Sheet
        theSheet(isWidthMax, context),
      ],
    );
  }

  Scaffold theSheet(bool isWidthMax, BuildContext context) {

    Scaffold generatedScaffold = genScaff(isWidthMax);

    EdgeInsetsGeometry padCheck = (((generatedScaffold.body as Flex).children[0] as Flexible).child as Container).padding;

    print("value " + padCheck.toString());

    return generatedScaffold;
  }

  Scaffold genScaff(bool isWidthMax) {
    return new Scaffold(
      body: new Flex(
        direction: (isWidthMax) ? Axis.vertical : Axis.horizontal,
        //ONLY relevant if position is top or bottom
        textDirection: (position == sheetPosition.right)
            ? TextDirection.ltr
            : TextDirection.rtl,
        //ONLY relevant if position is left or right
        verticalDirection: (position == sheetPosition.top)
            ? VerticalDirection.up
            : VerticalDirection.down,
        crossAxisAlignment: CrossAxisAlignment.stretch,
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          new Flexible(
              fit: FlexFit.loose,
              child: new Container(
                padding: EdgeInsets.all(18.3),
                color: Colors.red,
              )),
          new ConstrainedBox(
            constraints: _calcBoxConstraints(isWidthMax),
            child: new Container(
              color: Colors.purple,
              child: new Flex(
                direction: (isWidthMax) ? Axis.vertical : Axis.horizontal,
                //ONLY relevant if position is top or bottom
                textDirection: (position == sheetPosition.right)
                    ? (placement == attachmentPlacement.inside)
                    ? TextDirection.rtl
                    : TextDirection.ltr
                    : (placement == attachmentPlacement.inside)
                    ? TextDirection.ltr
                    : TextDirection.rtl,
                //ONLY relevant if position is left or right
                verticalDirection: (position == sheetPosition.top)
                    ? (placement == attachmentPlacement.inside)
                    ? VerticalDirection.down
                    : VerticalDirection.up
                    : (placement == attachmentPlacement.inside)
                    ? VerticalDirection.up
                    : VerticalDirection.down,
                crossAxisAlignment: CrossAxisAlignment.stretch,
                mainAxisAlignment: MainAxisAlignment.end,
                mainAxisSize: MainAxisSize.min,
                children: <Widget>[
                  new Container(
                    color: Colors.amberAccent,
                    child: sheet,
                  ),
                  new Flexible(
                    fit: FlexFit.loose,
                    child: new Container(
                      color: Colors.greenAccent,
                      child: (attachment != null) ? attachment : null,
                    ),
                  ),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}

person Bryan Cancel    schedule 10.06.2018    source источник
comment
Вопрос непонятный. Можете ли вы представить наглядный пример желаемого поведения? Даже если это ручной рисунок.   -  person Rémi Rousselet    schedule 10.06.2018
comment
отличная идея, сделаю это прямо сейчас   -  person Bryan Cancel    schedule 10.06.2018
comment
@ RémiRousselet Я добавил детали, которые вы просили ... любая помощь приветствуется   -  person Bryan Cancel    schedule 10.06.2018


Ответы (2)


Вам нужно обернуть свой внутренний Row в IntrinsicWidth, чтобы заставить его занимать как можно меньше места в зависимости от его содержимого.

Благодаря этому теперь вы можете без исключения обернуть дочерний элемент этой внутренней строки в Expanded.

введите описание изображения здесь

 new Row(
  crossAxisAlignment: CrossAxisAlignment.stretch,
  children: <Widget>[
    new Expanded(
      child: new Container(
        color: Colors.red,
      ),
    ),
    new ConstrainedBox(
      constraints: new BoxConstraints(minWidth: 100.0),
      child: new Container(
        color: Colors.purple,
        child: new IntrinsicWidth(
          child: new Row(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: <Widget>[
              new Container(
                color: Colors.cyan,
                child: new Icon(Icons.title),
              ),
              new Expanded(
                child: new Container(
                    color: Colors.yellow,
                    alignment: Alignment.center,
                    child: new Icon(Icons.theaters)),
              ),
            ],
          ),
        ),
      ),
    ),
  ],
),
person Rémi Rousselet    schedule 10.06.2018
comment
Большое спасибо за помощь! Я пробовал использовать внутреннюю ширину и высоту, но теперь понимаю, что использовал ее неправильно. Спасибо за пример! - person Bryan Cancel; 11.06.2018

Вам необходимо внести следующие изменения:

1.- Замените ConstrainedBox () на SizedBox ()

2.- Замените последний гибкий () расширенным (). Гибкость приспосабливается к размеру контейнера. Попробуйте это, удалив дочерний контейнер.

3.- И, наконец, поменяйте местами зеленый контейнер () и желтый контейнер (). В противном случае зеленый будет расширяться.

Это рабочий код для Scaffold:

  Scaffold genScaff(bool isWidthMax) {
    return new Scaffold(
      body: new Flex(
        direction: (isWidthMax) ? Axis.vertical : Axis.horizontal,
        //ONLY relevant if position is top or bottom
        textDirection: (position == sheetPosition.right)
            ? TextDirection.ltr
            : TextDirection.rtl,
        //ONLY relevant if position is left or right
        verticalDirection: (position == sheetPosition.top)
            ? VerticalDirection.up
            : VerticalDirection.down,
        crossAxisAlignment: CrossAxisAlignment.stretch,
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          new Flexible(
              fit: FlexFit.loose,
              child: new Container(
                padding: EdgeInsets.all(18.3),
                color: Colors.red,
              )),
          new SizedBox(
            width: 125.0, // Do your calculations based on isWidthMax
            height: double.infinity,
            //constraints: _calcBoxConstraints(isWidthMax),
            child: new Container(
              color: Colors.purple,
              child: new Flex(
                direction: (isWidthMax) ? Axis.vertical : Axis.horizontal,
                //ONLY relevant if position is top or bottom
                textDirection: (position == sheetPosition.right)
                    ? (placement == attachmentPlacement.inside)
                    ? TextDirection.rtl
                    : TextDirection.ltr
                    : (placement == attachmentPlacement.inside)
                    ? TextDirection.ltr
                    : TextDirection.rtl,
                //ONLY relevant if position is left or right
                verticalDirection: (position == sheetPosition.top)
                    ? (placement == attachmentPlacement.inside)
                    ? VerticalDirection.down
                    : VerticalDirection.up
                    : (placement == attachmentPlacement.inside)
                    ? VerticalDirection.up
                    : VerticalDirection.down,
                crossAxisAlignment: CrossAxisAlignment.stretch,
                mainAxisAlignment: MainAxisAlignment.end,
                mainAxisSize: MainAxisSize.min,
                children: <Widget>[
                  new Expanded(
                    child: new Container(
                      color: Colors.amberAccent,
                      child: sheet,
                    ),
                  ),
                  new Container(
                    color: Colors.greenAccent,
                    child: (attachment != null) ? attachment : null,
                  ),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }

И вот результат

введите здесь описание изображения

person chemamolins    schedule 10.06.2018
comment
Я ценю попытку, но здесь вы напрямую устанавливаете ширину, которая мне не очень помогает ... У меня есть минимальная и максимальная ширина ... но если ширина находится между этими двумя значениями, она будет рассчитана в зависимости от содержимого внутри контейнер ... не беспокойтесь об этом, решение remi работает - person Bryan Cancel; 15.06.2018