Skip to Content
Flutter📐 Layouts↔️ Expanded & Flexible

Expanded và Flexible trong Flutter

1. Expanded Widget

Expanded chiếm toàn bộ không gian còn lại trong Row/Column:

Row( children: [ Container(width: 50, height: 50, color: Colors.red), Expanded( child: Container(height: 50, color: Colors.green), // Chiếm hết phần còn lại ), Container(width: 50, height: 50, color: Colors.blue), ], )

2. Flex Factor

Khi có nhiều Expanded, dùng flex để phân chia tỷ lệ:

Row( children: [ Expanded( flex: 1, child: Container(height: 50, color: Colors.red), ), Expanded( flex: 2, // Gấp đôi phần đỏ child: Container(height: 50, color: Colors.green), ), Expanded( flex: 1, child: Container(height: 50, color: Colors.blue), ), ], ) // Kết quả: Red = 25%, Green = 50%, Blue = 25%

3. Flexible Widget

Flexible có thể chiếm không gian, nhưng không bắt buộc phải fill hết:

Row( children: [ Flexible( child: Container( width: 100, // Có thể nhỏ hơn available space height: 50, color: Colors.red, ), ), Container(width: 100, height: 50, color: Colors.blue), ], )

4. FlexFit

Flexible có property fit:

Flexible( fit: FlexFit.loose, // Mặc định - có thể nhỏ hơn child: Container(...), ) Flexible( fit: FlexFit.tight, // Buộc fill hết = Expanded child: Container(...), )
FitMô tả
FlexFit.looseChild có thể nhỏ hơn available space
FlexFit.tightChild phải fill hết available space

Expanded = Flexible với fit: FlexFit.tight


5. So sánh Expanded vs Flexible

Row( children: [ // Expanded: PHẢI fill hết Expanded( child: Container(height: 50, color: Colors.red), ), // Flexible (loose): CÓ THỂ nhỏ hơn Flexible( child: Container( width: 50, // Chỉ cần 50, không cần fill height: 50, color: Colors.blue, ), ), ], )

6. Ví dụ thực tế

Row( children: [ Expanded( child: TextField( decoration: InputDecoration(hintText: 'Search...'), ), ), SizedBox(width: 8), ElevatedButton(onPressed: () {}, child: Text('Search')), ], )

Two-column Layout

Row( children: [ Expanded( flex: 1, child: Container( color: Colors.grey[200], child: ListView(...), // Sidebar ), ), Expanded( flex: 3, child: Container( child: Content(), // Main content ), ), ], )

Form với Labels

Row( children: [ SizedBox( width: 100, child: Text('Username:'), ), Expanded( child: TextField(), ), ], )

7. Expanded trong Column

Column( children: [ AppBar(title: Text('Title')), // Fixed height Expanded( child: ListView(...), // Chiếm phần còn lại ), BottomNavigationBar(...), // Fixed height ], )

8. Lỗi thường gặp

Expanded ngoài Row/Column

// ❌ Lỗi: Expanded phải trong Row, Column, hoặc Flex Container( child: Expanded( child: Text('Error'), ), ) // ✅ Đúng Row( children: [ Expanded(child: Text('OK')), ], )

Nhiều Expanded không có kích thước

// ❌ Có thể gây lỗi nếu không có bounded constraints Column( children: [ Expanded(child: Container()), Expanded(child: Container()), ], ) // ✅ Đảm bảo Column có bounded height SizedBox( height: 400, child: Column( children: [ Expanded(child: Container(color: Colors.red)), Expanded(child: Container(color: Colors.blue)), ], ), )

📝 Tóm tắt

WidgetBehaviorKhi nào dùng
ExpandedBuộc fill hết không gianMuốn stretch child
Flexible(loose)Có thể nhỏ hơnChild có kích thước riêng
Flexible(tight)= ExpandedHiếm khi dùng trực tiếp

Flex factor:

  • flex: 1 → 1 phần
  • flex: 2 → 2 phần
  • Tổng = tổng các flex, chia theo tỷ lệ
Last updated on