Эквивалент wrap_content и match_parent во флаттере?


128

В Android match_parentи wrap_contentиспользуются для изменения размера виджетов автоматически относительно их родителей к содержанию виджет содержит.

Во Flutter кажется, что по умолчанию для всех виджетов установлено значение wrap_content, как мне изменить его так, чтобы я мог заполнить его widthи heightего родительский?

Ответы:


170

Вы можете сделать небольшой трюк: предположим, у вас есть требования: (ширина, высота)

Wrap_content, Wrap_content:

 //use this as child
 Wrap(
  children: <Widget>[*your_child*])

Match_parent, Match_parent:

 //use this as child
Container(
        height: double.infinity,
    width: double.infinity,child:*your_child*)

Match_parent, Wrap_content:

 //use this as child
Row(
  mainAxisSize: MainAxisSize.max,
  children: <Widget>[*your_child*],
);

Wrap_content, Match_parent:

 //use this as child
Column(
  mainAxisSize: MainAxisSize.max,
  children: <Widget>[your_child],
);

2
чтобы соответствовать родителю, вы также можете обернуть свои виджеты с помощью SizedBox.expand ()
Вехеровски

138

Для того , чтобы получить поведение для match_parent и wrap_content мы должны использовать mainAxisSize свойство в строки / столбца виджета, то mainAxisSize свойство принимает MainAxisSize перечисление , имеющее два значения, является MainAxisSize.min , который ведет себя как wrap_content и MainAxisSize.max , который ведет себя как match_parent .

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

Ссылка на оригинальную статью


6
Я бы добавил, что есть также crossAxisAlignmentполе для строк и столбцов, которое можно настроить для CrossAxisAlignment.stretchгоризонтального расширения, например, внутри столбца
wamfous

1
Большое спасибо! Проголосовал в прошлом году, потом давно не пользовался флаттером и почти все забыл, а сегодня вы снова мне помогли.
Чендлер

33

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

Макет работает во Flutter так: каждый виджет предоставляет ограничения для каждого из своих дочерних элементов, например «вы можете быть до этой ширины, вы должны быть такими высокими, вы должны быть как минимум такими же» или что-то еще (в частности, они получить минимальную ширину, максимальную ширину, минимальную высоту и максимальную высоту). Каждый дочерний элемент принимает эти ограничения, что-то делает и выбирает размер (ширину и высоту), который соответствует этим ограничениям. Затем, когда каждый дочерний элемент сделает свое дело, виджет может выбрать свой размер.

Некоторые виджеты стараются быть настолько большими, насколько позволяет родитель. Некоторые виджеты стараются быть настолько маленькими, насколько позволяет родитель. Некоторые виджеты пытаются соответствовать определенному «естественному» размеру (например, тексту, изображениям).

Некоторые виджеты сообщают своим детям, что они могут быть любого размера. Некоторые накладывают на своих детей те же ограничения, что и их родители.


Ян, когда у меня есть PageViewвнутри a Column, а другой Columnвнутри текущего page, я получаю ошибку рендеринга, но я могу исправить ее, PageViewзаключив внутрь a Expandedили a Flexible. Проблема в том, что эти 2 варианта только расширяют своего ребенка. Почему нет соответствующего виджета, который можно было бы сжать, например "обернуть содержимое", для решения такого рода проблем рендеринга?
Мишель Файнштейн

21

На самом деле доступны несколько вариантов:

Вы можете использовать SizedBox.expand, чтобы ваш виджет соответствовал родительским размерам, или SizedBox (width: double.infinity), чтобы соответствовать только ширине, или SizedBox (heigth: double.infinity), чтобы соответствовать только высоте.

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

С помощью ListView кнопка получает поведение match_parent, а чтобы получить поведение wrap_content, вы можете обернуть ее с помощью виджета Flex, такого как Row.

Использование расширенного виджета заставляет дочерний элемент строки, столбца или гибкого элемента расширяться, чтобы заполнить доступное пространство на главной оси (например, по горизонтали для строки или по вертикали для столбца). https://docs.flutter.io/flutter/widgets/Expanded-class.html

Использование гибкого виджета дает дочернему элементу строки, столбца или гибкости возможность расширяться, чтобы заполнить доступное пространство на главной оси (например, по горизонтали для строки или по вертикали для столбца), но, в отличие от расширенного, гибкий не требовать, чтобы ребенок заполнил доступное пространство. https://docs.flutter.io/flutter/widgets/F flexible-class.html


7

Простой обходной путь:

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

Container(color:Colors.white,height:200.0,width:200.0,
 child:Container(
    color: Colors.yellow,
    alignment:Alignment.[any_available_option] // make the yellow child match the parent size
   )
)

По-другому:

Container(color:Colors.white,height:200.0,width:200.0,
 child:Container(
    color: Colors.yellow,
    constraints:  BoxConstraints.expand(height: 100.0), // height will be 100 dip and width will be match parent
   )
)

BoxConstraints.expand(height: 100.0)отлично работает как width="match_parent"эквивалент Android
kosiara - Bartosz Kosarzycki

7

Я использовал это решение, вам нужно определить высоту и ширину экрана с помощью MediaQuery:

 Container(
        height: MediaQuery.of(context).size.height,
        width: MediaQuery.of(context).size.width
  )

5
Stack(
  children: [
    Container(color:Colors.red, height:200.0, width:200.0),
    Positioned.fill(
      child: Container(color: Colors. yellow),
    )
  ]
),

1
Хотя ваш код может ответить на вопрос, хороший ответ всегда должен объяснять, что делает код и как он решает проблему.
BDL

это не ответ на перенос содержимого. это просто жестко заданные ширина и высота.
Developine

1

Используйте виджет Wrap.

Для Columnподобного поведения попробуйте:

  return Wrap(
          direction: Axis.vertical,
          spacing: 10,
          children: <Widget>[...],);

Для Rowподобного поведения попробуйте:

  return Wrap(
          direction: Axis.horizontal,
          spacing: 10,
          children: <Widget>[...],);

Для получения дополнительной информации: Wrap (виджет Flutter)


0

Используйте эту строку кодов внутри столбца. Для wrap_content: mainAxisSize: MainAxisSize.min Для match_parent:mainAxisSize: MainAxisSize.max


0

На самом деле есть очень простой и изящный способ сделать это.

Используйте FractionallySizedBoxвиджет.

FractionallySizedBox(
  widthFactor: 1.0, // width w.r.t to parent
  heightFactor: 1.0,  // height w.r.t to parent
  child: *Your Child Here*
}

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

Пример:

Если вы хотите, чтобы дочерний элемент занимал 50% ширины своего родителя, укажите widthFactorкак0.5


0

Чтобы дочерний элемент заполнил своего родителя, просто оберните его в FittedBox.

    FittedBox(
     child: Image.asset('foo.png'),
     fit: BoxFit.fill,
   )
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.