© Khmer Angkor Academy - sophearithput168

Flutter Layouts

Layout Widgets ក្នុង Flutter

Layout widgets ប្រើសម្រាប់រៀបចំ widgets ផ្សេងទៀត។ ពួកវាកំណត់ទីតាំង និង ទំហំ របស់ children widgets។

📚 Layout Theory

Flutter Layout Algorithm (3 Steps):

1. Constraints go DOWN
   Parent → Child: "You must be THIS size"
   
2. Sizes go UP
   Child → Parent: "I chose THIS size"
   
3. Parent sets position
   Parent positions child based on alignment

Box Constraints:

Flutter ប្រើ Box Constraints ដើម្បីកំណត់ទំហំ widget:

BoxConstraints(
  minWidth: 0,      // ទំហំតូចបំផុត
  maxWidth: 100,    // ទំហំធំបំផុត
  minHeight: 0,
  maxHeight: 200,
)

// Types of constraints:
// 1. Tight: minWidth == maxWidth (fixed size)
// 2. Loose: minWidth < maxWidth (flexible size)
// 3. Unbounded: maxWidth = infinity

Layout Rules:

  • Rule 1: Widget មិនអាចធំជាង parent constraints
  • Rule 2: Widget អាចតូចជាង parent constraints (ប្រសិនបើ parent អនុញ្ញាត)
  • Rule 3: Widget ត្រូវដឹងទីតាំងរបស់វា (x, y)
  • Rule 4: Parent កំណត់ទីតាំង child មិនមែន child កំណត់ខ្លួនឯងទេ

⚠️ សំខាន់: "Constraints go down. Sizes go up. Parent sets position." - នេះគឺជា golden rule នៃ Flutter layout!

📐 Main Layout Widgets

1. Container

Container គឺជា widget ពេញនិយម និងអាចប្រើបានច្រើន។

Container(
  width: 200,
  height: 100,
  padding: EdgeInsets.all(16),
  margin: EdgeInsets.symmetric(horizontal: 20, vertical: 10),
  decoration: BoxDecoration(
    color: Colors.blue,
    borderRadius: BorderRadius.circular(12),
    gradient: LinearGradient(
      colors: [Colors.blue, Colors.purple],
    ),
    boxShadow: [
      BoxShadow(
        color: Colors.grey.withOpacity(0.5),
        blurRadius: 10,
        offset: Offset(0, 5),
      ),
    ],
    border: Border.all(color: Colors.white, width: 2),
  ),
  child: Text(
    'Container',
    style: TextStyle(color: Colors.white),
  ),
)

2. Row - តម្រៀបផ្ដេក (Horizontal)

Row(
  mainAxisAlignment: MainAxisAlignment.spaceEvenly,  // ចន្លោះស្មើគ្នា
  crossAxisAlignment: CrossAxisAlignment.center,      // កណ្តាលបញ្ឈរ
  children: [
    Icon(Icons.star, color: Colors.yellow),
    Icon(Icons.star, color: Colors.yellow),
    Icon(Icons.star, color: Colors.yellow),
    Icon(Icons.star_border),
    Icon(Icons.star_border),
  ],
)

// MainAxisAlignment values:
// - start: ខាងឆ្វេង
// - end: ខាងស្តាំ
// - center: កណ្តាល
// - spaceBetween: ចន្លោះរវាង (ធំបំផុត)
// - spaceAround: ចន្លោះជុំវិញ (កណ្តាល)
// - spaceEvenly: ចន្លោះស្មើគ្នា

3. Column - តម្រៀបបញ្ឈរ (Vertical)

Column(
  mainAxisAlignment: MainAxisAlignment.center,
  crossAxisAlignment: CrossAxisAlignment.start,  // ខាងឆ្វេង
  children: [
    Text('ឈ្មោះ៖ សុខា'),
    SizedBox(height: 8),
    Text('អាយុ៖ 20 ឆ្នាំ'),
    SizedBox(height: 8),
    Text('ទីក្រុង៖ ភ្នំពេញ'),
  ],
)

// CrossAxisAlignment values:
// - start: ខាងឆ្វេង/លើ
// - end: ខាងស្តាំ/ក្រោម
// - center: កណ្តាល
// - stretch: រាតត្រដាង
// - baseline: តាមបន្ទាត់មូលដ្ឋាន

4. Stack - ដាក់ជាន់គ្នា

Stack(
  children: [
    // Background image
    Container(
      width: 300,
      height: 200,
      color: Colors.blue,
    ),
    // Overlay text
    Positioned(
      bottom: 20,
      left: 20,
      child: Text(
        'រូបភាព',
        style: TextStyle(
          color: Colors.white,
          fontSize: 24,
          fontWeight: FontWeight.bold,
        ),
      ),
    ),
    // Top right badge
    Positioned(
      top: 10,
      right: 10,
      child: Container(
        padding: EdgeInsets.all(8),
        decoration: BoxDecoration(
          color: Colors.red,
          shape: BoxShape.circle,
        ),
        child: Text(
          '5',
          style: TextStyle(color: Colors.white),
        ),
      ),
    ),
  ],
)

5. Expanded & Flexible

Row(
  children: [
    // Fixed width
    Container(
      width: 100,
      height: 50,
      color: Colors.red,
    ),
    
    // Takes remaining space
    Expanded(
      child: Container(
        height: 50,
        color: Colors.blue,
      ),
    ),
    
    // Fixed width
    Container(
      width: 80,
      height: 50,
      color: Colors.green,
    ),
  ],
)

// Expanded with flex ratio
Row(
  children: [
    Expanded(
      flex: 1,  // 25% (1/4)
      child: Container(color: Colors.red, height: 50),
    ),
    Expanded(
      flex: 2,  // 50% (2/4)
      child: Container(color: Colors.blue, height: 50),
    ),
    Expanded(
      flex: 1,  // 25% (1/4)
      child: Container(color: Colors.green, height: 50),
    ),
  ],
)

6. Wrap - តម្រៀបដោយបត់បាន

Wrap(
  spacing: 8,      // ចន្លោះផ្ដេក
  runSpacing: 8,   // ចន្លោះបញ្ឈរ
  children: [
    Chip(label: Text('Flutter')),
    Chip(label: Text('Dart')),
    Chip(label: Text('Mobile')),
    Chip(label: Text('iOS')),
    Chip(label: Text('Android')),
    Chip(label: Text('Web')),
    Chip(label: Text('Desktop')),
  ],
)

📏 Sizing & Spacing

SizedBox

// Fixed size
SizedBox(
  width: 200,
  height: 100,
  child: ElevatedButton(
    onPressed: () {},
    child: Text('Button'),
  ),
)

// Spacing
Column(
  children: [
    Text('Text 1'),
    SizedBox(height: 20),  // ចន្លោះ 20px
    Text('Text 2'),
  ],
)

Padding

Padding(
  padding: EdgeInsets.all(16),  // ទាំងអស់ 16px
  child: Text('Padded text'),
)

// Different padding
Padding(
  padding: EdgeInsets.only(
    left: 20,
    top: 10,
    right: 20,
    bottom: 10,
  ),
  child: Text('Text'),
)

// Symmetric padding
Padding(
  padding: EdgeInsets.symmetric(
    horizontal: 20,  // ឆ្វេង-ស្តាំ
    vertical: 10,    // លើ-ក្រោម
  ),
  child: Text('Text'),
)

Center & Align

// Center
Center(
  child: Text('កណ្តាល'),
)

// Align
Align(
  alignment: Alignment.topRight,
  child: Icon(Icons.close),
)

// Alignment values:
// topLeft, topCenter, topRight
// centerLeft, center, centerRight
// bottomLeft, bottomCenter, bottomRight

🎨 Real Layout Example

class ProfilePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('ប្រវត្តិរូប'),
      ),
      body: SingleChildScrollView(
        child: Column(
          children: [
            // Header with background
            Stack(
              children: [
                Container(
                  height: 200,
                  decoration: BoxDecoration(
                    gradient: LinearGradient(
                      colors: [Colors.blue, Colors.purple],
                    ),
                  ),
                ),
                Positioned(
                  bottom: 20,
                  left: 0,
                  right: 0,
                  child: Center(
                    child: CircleAvatar(
                      radius: 50,
                      backgroundImage: NetworkImage('https://example.com/avatar.jpg'),
                    ),
                  ),
                ),
              ],
            ),
            
            SizedBox(height: 20),
            
            // Name and bio
            Padding(
              padding: EdgeInsets.symmetric(horizontal: 20),
              child: Column(
                children: [
                  Text(
                    'សុខា',
                    style: TextStyle(
                      fontSize: 24,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                  SizedBox(height: 8),
                  Text(
                    'Flutter Developer',
                    style: TextStyle(
                      color: Colors.grey,
                      fontSize: 16,
                    ),
                  ),
                ],
              ),
            ),
            
            SizedBox(height: 20),
            
            // Stats row
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                _buildStat('150', 'Posts'),
                _buildStat('1.2K', 'Followers'),
                _buildStat('300', 'Following'),
              ],
            ),
            
            SizedBox(height: 20),
            
            // Action buttons
            Padding(
              padding: EdgeInsets.symmetric(horizontal: 20),
              child: Row(
                children: [
                  Expanded(
                    child: ElevatedButton(
                      onPressed: () {},
                      child: Text('Follow'),
                    ),
                  ),
                  SizedBox(width: 10),
                  Expanded(
                    child: OutlinedButton(
                      onPressed: () {},
                      child: Text('Message'),
                    ),
                  ),
                ],
              ),
            ),
            
            SizedBox(height: 20),
            
            // Posts grid
            GridView.count(
              shrinkWrap: true,
              physics: NeverScrollableScrollPhysics(),
              crossAxisCount: 3,
              crossAxisSpacing: 4,
              mainAxisSpacing: 4,
              children: List.generate(9, (index) {
                return Container(
                  color: Colors.grey[300],
                  child: Center(
                    child: Icon(Icons.image, size: 50),
                  ),
                );
              }),
            ),
          ],
        ),
      ),
    );
  }
  
  Widget _buildStat(String count, String label) {
    return Column(
      children: [
        Text(
          count,
          style: TextStyle(
            fontSize: 20,
            fontWeight: FontWeight.bold,
          ),
        ),
        SizedBox(height: 4),
        Text(
          label,
          style: TextStyle(color: Colors.grey),
        ),
      ],
    );
  }
}

💡 ជំនួយ: ប្រើ Flutter DevTools Widget Inspector ដើម្បីមើល និង debug layout issues។ វាបង្ហាញ widget tree និង constraints របស់ widget នីមួយៗ។