← Назад к вопросам

В чём разница между Expanded и Flexible виджетами?

1.0 Junior🔥 192 комментариев
#Flutter виджеты

Комментарии (2)

🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Expanded vs Flexible в Flutter

Оба виджета используются внутри Row/Column для управления распределением пространства, но работают по-разному.

Что их объединяет?

Оба виджета:

  • Оборачивают дочерние элементы
  • Работают только в Flex контейнерах (Row, Column)
  • Имеют параметр flex (по умолчанию 1)
  • Занимают доступное пространство

Flexible — гибкий, но не обязательный

Flexible позволяет виджету занять доступное пространство, но без обязательности. Если пространства нет — виджет сжимается до своего минимального размера.

Row(
  children: [
    Container(width: 100, color: Colors.blue, height: 50),
    Flexible(
      flex: 1,
      fit: FlexFit.loose, // может быть меньше доступного пространства
      child: Container(color: Colors.red, height: 50),
    ),
    Container(width: 100, color: Colors.green, height: 50),
  ],
)

Параметр fit:

  • FlexFit.loose (по умолчанию) — виджет может быть меньше доступного пространства
  • FlexFit.tight — виджет обязательно займёт всё доступное пространство

Expanded — всегда займёт пространство

Expanded — это Flexible с fit: FlexFit.tight. Виджет обязательно займёт все доступное пространство, не может быть меньше.

Row(
  children: [
    Container(width: 100, color: Colors.blue, height: 50),
    Expanded(
      flex: 1,
      child: Container(color: Colors.red, height: 50), // займёт всё свободное место
    ),
    Container(width: 100, color: Colors.green, height: 50),
  ],
)

Это эквивалентно:

Flexible(
  flex: 1,
  fit: FlexFit.tight,
  child: Container(color: Colors.red, height: 50),
)

Практическая разница

Сценарий 1: Кнопка внутри Row

Row(
  children: [
    Flexible(
      child: ElevatedButton(
        onPressed: () {},
        child: Text(Кнопка),
      ),
    ),
  ],
)
// Результат: кнопка займёт только нужный размер, даже если пространства много

Сценарий 2: Растягивающееся поле ввода

Row(
  children: [
    Text(Поиск:),
    Expanded(
      child: TextField(
        // займёт ВСЁ оставшееся место
      ),
    ),
  ],
)

Параметр flex — распределение пространства

Если несколько Flexible/Expanded виджетов с разными flex:

Row(
  children: [
    Expanded(
      flex: 2,
      child: Container(color: Colors.red),
    ),
    Expanded(
      flex: 1,
      child: Container(color: Colors.blue),
    ),
  ],
)
// Red займёт 2/3 пространства, Blue — 1/3

Сравнительная таблица

ПараметрFlexibleExpanded
Обязательно займёт местоНет (loose по умолчанию)Да
Может быть меньше доступногоДаНет
Fit по умолчаниюFlexFit.looseFlexFit.tight
Управление flexДаДа
ИспользованиеГибкие элементы (кнопки, тексты)Растягивающиеся элементы (поля ввода)

Правило большого пальца

  • Expanded — когда нужно обязательно заполнить пространство (TextField, контент)
  • Flexible — когда элемент может быть меньше, но может вырасти если место есть (кнопки, иконки)

Пример: Форма логина

Column(
  children: [
    // Заголовок — не растягивается
    Text(Вход),
    
    SizedBox(height: 20),
    
    // Поле Email — ОБЯЗАТЕЛЬНО растянуть
    Expanded(
      child: TextField(decoration: InputDecoration(label: Text(Email))),
    ),
    
    SizedBox(height: 10),
    
    // Поле пароля — ОБЯЗАТЕЛЬНО растянуть
    Expanded(
      child: TextField(decoration: InputDecoration(label: Text(Пароль))),
    ),
    
    SizedBox(height: 20),
    
    // Кнопка — займёт свой размер, может быть меньше
    Flexible(
      child: ElevatedButton(child: Text(Войти)),
    ),
  ],
)

Вывод: Expanded = Flexible + FlexFit.tight. Используй Expanded для обязательного заполнения пространства, Flexible для гибких элементов.