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

Где применяется Expanded?

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

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

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

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

Где и как применяется виджет Expanded в Flutter

Expanded — это виджет в Flutter, который заставляет дочерний элемент занимать всё доступное пространство в родительском Row или Column.

Основное использование

// Базовое использование Expanded
Row(
  children: [
    Container(width: 100, height: 50, color: Colors.red),
    Expanded(
      child: Container(color: Colors.green), // Займёт всё оставшееся место
    ),
    Container(width: 100, height: 50, color: Colors.blue),
  ],
)

// Результат: красный(100) + зелёный(всё оставшееся) + синий(100)

Как это работает:

  • В контексте Row/Column — Expanded растягивает виджет на всё доступное пространство
  • Параметр flex — определяет, сколько доли пространства займёт виджет
  • Обязателен Row или Column — вне этих контейнеров Expanded не работает

Параметр flex (пропорции)

// flex определяет соотношение размеров
Row(
  children: [
    Expanded(
      flex: 1, // Займёт 1/4 пространства
      child: Container(color: Colors.red),
    ),
    Expanded(
      flex: 2, // Займёт 2/4 пространства (в два раза больше)
      child: Container(color: Colors.green),
    ),
    Expanded(
      flex: 1, // Займёт 1/4 пространства
      child: Container(color: Colors.blue),
    ),
  ],
)

// Пропорции: красный 25% + зелёный 50% + синий 25%

Практические примеры использования

1. Раскладка кнопок в строку:

// Кнопки одинакового размера, распределённые по ширине
Row(
  children: [
    Expanded(
      child: ElevatedButton(
        onPressed: () {},
        child: Text('Cancel'),
      ),
    ),
    SizedBox(width: 16), // Промежуток
    Expanded(
      child: ElevatedButton(
        onPressed: () {},
        child: Text('OK'),
      ),
    ),
  ],
)

2. Форма с полями ввода:

// Поле ввода занимает всё оставшееся место
Row(
  children: [
    Text('Email: '),
    Expanded(
      child: TextField(
        decoration: InputDecoration(
          hintText: 'Enter email',
          border: OutlineInputBorder(),
        ),
      ),
    ),
  ],
)

3. Список с элементами разных размеров:

ListTile(
  leading: CircleAvatar(child: Text('A')),
  title: Text('Alice'),
  subtitle: Text('Active 5 minutes ago'),
  trailing: Icon(Icons.more_vert),
)

// Или вручную:
Row(
  children: [
    CircleAvatar(child: Text('A')),
    SizedBox(width: 16),
    Expanded(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text('Alice'),
          Text('Active 5 minutes ago', style: TextStyle(fontSize: 12)),
        ],
      ),
    ),
    Icon(Icons.more_vert),
  ],
)

4. Header с логотипом и меню:

Row(
  children: [
    Image.asset('logo.png', width: 50, height: 50),
    SizedBox(width: 16),
    Expanded(
      child: Text(
        'My App',
        style: Theme.of(context).textTheme.headlineSmall,
      ),
    ),
    IconButton(icon: Icon(Icons.menu), onPressed: () {}),
  ],
)

5. Card с содержимым и действиями:

Card(
  child: Column(
    children: [
      Row(
        children: [
          Image.network('image.jpg', width: 80, height: 80),
          SizedBox(width: 16),
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text('Product Name'),
                Text('Price: \$99.99'),
                SizedBox(height: 8),
                ElevatedButton(
                  onPressed: () {},
                  child: Text('Add to Cart'),
                ),
              ],
            ),
          ),
        ],
      ),
    ],
  ),
)

Expanded vs другие виджеты

Expanded vs Flexible:

// Expanded - всегда занимает максимум доступного пространства
Row(
  children: [
    Expanded(
      child: Text('This will be stretched'),
    ),
  ],
)

// Flexible - может занять меньше, если дочерний виджет меньше
Row(
  children: [
    Flexible(
      child: Text('This might not be stretched'),
    ),
  ],
)

Expanded vs SizedBox:

// Expanded - занимает всё доступное место
// Хорошо, когда размер заранее неизвестен
Row(
  children: [
    Expanded(
      child: Container(color: Colors.red),
    ),
  ],
)

// SizedBox - фиксированный размер
// Хорошо, когда размер известен
Row(
  children: [
    SizedBox(
      width: 100,
      child: Container(color: Colors.red),
    ),
  ],
)

Ошибки при использовании Expanded

Ошибка 1: Expanded вне Row/Column

// ОШИБКА - Expanded не может быть здесь
Scaffold(
  body: Expanded(
    child: Text('Error'),
  ),
)

// ПРАВИЛЬНО - используй Expanded в Row/Column
Scaffold(
  body: Row(
    children: [
      Expanded(
        child: Text('OK'),
      ),
    ],
  ),
)

Ошибка 2: Nested Expanded без правильной конфигурации

// Может быть проблема
Column(
  children: [
    Expanded(
      child: Row(
        children: [
          Expanded(
            child: Text('A'),
          ),
          Expanded(
            child: Text('B'),
          ),
        ],
      ),
    ),
  ],
)

// Лучше явно указать mainAxisSize
Column(
  mainAxisSize: MainAxisSize.max,
  children: [
    Expanded(
      child: Row(
        mainAxisSize: MainAxisSize.max,
        children: [
          Expanded(child: Text('A')),
          Expanded(child: Text('B')),
        ],
      ),
    ),
  ],
)

Примеры из реальных приложений

Профиль пользователя:

Widget buildUserProfile() {
  return Column(
    children: [
      Container(
        color: Colors.blue,
        height: 200,
        child: Center(
          child: CircleAvatar(radius: 50),
        ),
      ),
      SizedBox(height: 16),
      Row(
        children: [
          SizedBox(width: 16),
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text('John Doe', style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
                Text('john@example.com'),
                SizedBox(height: 16),
                ElevatedButton(
                  onPressed: () {},
                  child: Text('Follow'),
                ),
              ],
            ),
          ),
          Icon(Icons.more_vert),
          SizedBox(width: 16),
        ],
      ),
    ],
  );
}

Chat bubble:

Widget buildChatBubble(String message, bool isMe) {
  return Row(
    mainAxisAlignment: isMe ? MainAxisAlignment.end : MainAxisAlignment.start,
    children: [
      if (!isMe) SizedBox(width: 8),
      Expanded(
        child: Container(
          margin: EdgeInsets.all(8),
          padding: EdgeInsets.all(12),
          decoration: BoxDecoration(
            color: isMe ? Colors.blue : Colors.grey,
            borderRadius: BorderRadius.circular(12),
          ),
          child: Text(
            message,
            style: TextStyle(color: Colors.white),
          ),
        ),
      ),
      if (isMe) SizedBox(width: 8),
    ],
  );
}

Когда НЕ использовать Expanded

  • Когда размер известен — используй SizedBox с явным размером
  • Для центрирования — используй Center или MainAxisAlignment
  • Вне Row/Column — используй FractionallySizedBox или MediaQuery
  • Для padding/margin — используй Padding и Margin вместо Expanded

Expanded — это незаменимый виджет для создания адаптивных интерфейсов, которые правильно распределяют пространство между элементами.