8 Widget Flutter untuk Pemula :

darsurplsmknesaba
0
8 Widget Flutter untuk Pemula: Bikin Aplikasi Color Match Outfit
Tutorial Flutter · Pemula

8 Widget Flutter untuk Pemula

Bikin aplikasi Color Match Outfit dari nol — lengkap dengan penjelasan, kode siap pakai, dan preview tampilan.

🛠Persiapan Awal

Sebelum mulai, pastikan Flutter sudah terpasang di komputer kamu. Jalankan perintah berikut di terminal:

terminal
# 1. Buat project baru
flutter create color_match_outfit
cd color_match_outfit

# 2. Jalankan aplikasi
flutter run

Struktur Folder yang Disarankan

color_match_outfit/ ├── assets/ │ └── images/ │ └── outfit1.jpg ├── lib/ │ └── main.dart └── pubspec.yaml

Konfigurasi pubspec.yaml (untuk Materi 2)

pubspec.yaml
flutter:
  uses-material-design: true
  assets:
    - assets/images/
⚠️ Setelah mengedit pubspec.yaml, jalankan flutter pub get dan restart aplikasi agar asset dikenali.

1Text Widget

🎯 Tujuan: Siswa mampu menampilkan tulisan dan mengatur tampilannya (ukuran, warna, ketebalan).

📚 Penjelasan

Widget Text menampilkan teks. Tampilannya diatur lewat TextStyle.

PropertiFungsiContoh
fontSizeUkuran huruf24
colorWarna teksColors.white
fontWeightKetebalanFontWeight.bold
fontStyleMiring / normalFontStyle.italic
letterSpacingJarak antar huruf1.5
textAlignPerataan teksTextAlign.center

💻 Kode Lengkap

lib/materi1_page.dart
import 'package:flutter/material.dart';

class Materi1Page extends StatelessWidget {
  const Materi1Page({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: const Color(0xFFF5EFE6),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: const [
            Text(
              'Color Match Outfit',
              style: TextStyle(
                fontSize: 32,
                fontWeight: FontWeight.bold,
                color: Color(0xFF6B4F3B),
                letterSpacing: 1.2,
              ),
              textAlign: TextAlign.center,
            ),
            SizedBox(height: 12),
            Text(
              'Temukan paduan warna pakaian\nterbaik untukmu!',
              style: TextStyle(
                fontSize: 16,
                color: Colors.brown,
                fontStyle: FontStyle.italic,
              ),
              textAlign: TextAlign.center,
            ),
          ],
        ),
      ),
    );
  }
}
Hasil Tampilan
┌─────────────────────────────┐ │ │ │ Color Match Outfit │ ← besar, bold, coklat │ │ │ Temukan paduan warna │ ← miring, ukuran 16 │ pakaian terbaik untukmu! │ │ │ └─────────────────────────────┘

Buat tampilan judul aplikasi Color Match Outfit dengan tulisan dan deskripsi (contoh di atas).


2Image Widget

🎯 Tujuan: Siswa mampu menampilkan gambar dari folder assets.

📚 Penjelasan

PropertiFungsi
Image.asset('path')Ambil gambar dari folder project
width / heightUkuran gambar (px)
fit: BoxFit.coverIsi area tanpa distorsi (crop)
fit: BoxFit.containMuat seluruh gambar
fit: BoxFit.fillRegangkan (bisa gepeng)

Langkah Konfigurasi

  1. Siapkan gambar, misal outfit1.jpg.
  2. Letakkan di assets/images/outfit1.jpg.
  3. Daftarkan di pubspec.yaml.
  4. Jalankan flutter pub get lalu restart.

💻 Kode Lengkap

lib/materi2_page.dart
import 'package:flutter/material.dart';

class Materi2Page extends StatelessWidget {
  const Materi2Page({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Galeri Outfit')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ClipRRect(
              borderRadius: BorderRadius.circular(16),
              child: Image.asset(
                'assets/images/outfit1.jpg',
                width: 250,
                height: 300,
                fit: BoxFit.cover,
              ),
            ),
            const SizedBox(height: 16),
            const Text(
              'Outfit Earth Tone',
              style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
            ),
          ],
        ),
      ),
    );
  }
}
Hasil Tampilan
┌─────────────────────────────┐ │ ← Galeri Outfit │ ├─────────────────────────────┤ │ ╭───────────╮ │ │ │ │ │ │ │ GAMBAR │ 250×300│ │ │ OUTFIT │ cover │ │ ╰───────────╯ │ │ Outfit Earth Tone │ └─────────────────────────────┘
💡 Tips: Jika gambar tidak muncul → cek (1) path di pubspec, (2) nama file, (3) sudah flutter pub get & restart.

Tampilkan gambar outfit dengan BoxFit.cover (contoh di atas).


3Container Widget

🎯 Tujuan: Siswa mampu membuat "kotak" sebagai wadah, mengatur warna, padding, margin, dan sudut melengkung.

📚 Penjelasan

PropertiFungsi
width / heightUkuran kotak
colorWarna latar (jangan dipakai jika ada decoration)
paddingJarak isi ke tepi dalam
marginJarak kotak ke elemen luar
decoration: BoxDecoration()Border, radius, gradien
borderRadiusSudut melengkung
⚠️ Penting: Jika pakai decoration, jangan pakai color di Container. Taruh warna di dalam BoxDecoration(color: ...).

💻 Kode Lengkap — Pilihan Warna Earth Tone

lib/materi3_page.dart
import 'package:flutter/material.dart';

class Materi3Page extends StatelessWidget {
  const Materi3Page({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: const Color(0xFFF5EFE6),
      appBar: AppBar(title: const Text('Pilihan Warna')),
      body: Center(
        child: Wrap(
          spacing: 16,
          runSpacing: 16,
          alignment: WrapAlignment.center,
          children: const [
            ColorBox(color: Color(0xFF8B7355), label: 'Taupe'),
            ColorBox(color: Color(0xFFA67B5B), label: 'Caramel'),
            ColorBox(color: Color(0xFF6B4F3B), label: 'Brown'),
            ColorBox(color: Color(0xFFD2B48C), label: 'Tan'),
          ],
        ),
      ),
    );
  }
}

class ColorBox extends StatelessWidget {
  final Color color;
  final String label;
  const ColorBox({super.key, required this.color, required this.label});

  @override
  Widget build(BuildContext context) {
    return Container(
      width: 140,
      height: 140,
      margin: const EdgeInsets.all(4),
      padding: const EdgeInsets.all(8),
      decoration: BoxDecoration(
        color: color,
        borderRadius: BorderRadius.circular(20),
        boxShadow: const [
          BoxShadow(color: Colors.black26, blurRadius: 6, offset: Offset(2, 3)),
        ],
      ),
      child: Center(
        child: Text(
          label,
          style: const TextStyle(
            color: Colors.white,
            fontWeight: FontWeight.bold,
            fontSize: 16,
          ),
        ),
      ),
    );
  }
}
Hasil Tampilan
┌─────────────────────────────┐ │ ← Pilihan Warna │ ├─────────────────────────────┤ │ ╭──────╮ ╭───────╮ │ │ │Taupe │ │Caramel│ │ │ ╰──────╯ ╰───────╯ │ │ ╭──────╮ ╭──────╮ │ │ │Brown │ │ Tan │ │ │ ╰──────╯ ╰──────╯ │ └─────────────────────────────┘

Buat kotak pilihan warna dengan sudut melengkung (contoh di atas).


4Icon Widget

🎯 Tujuan: Siswa mampu memakai ikon untuk memperjelas fungsi aplikasi.

📚 Penjelasan

PropertiFungsi
Icon(Icons.nama)Menampilkan ikon bawaan
sizeUkuran ikon
colorWarna ikon

Perbedaan Icon vs Image

  • Icon → simbol vektor, ringan, ikut berubah warna (Icons.palette, Icons.colorize).
  • Image → gambar raster/foto, tidak bisa di-recolor otomatis.

💻 Kode Lengkap — Kumpulan Ikon Color Match

lib/materi4_page.dart
import 'package:flutter/material.dart';

class Materi4Page extends StatelessWidget {
  const Materi4Page({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Ikon Color Match')),
      body: Center(
        child: Wrap(
          spacing: 30,
          runSpacing: 30,
          alignment: WrapAlignment.center,
          children: const [
            IconItem(icon: Icons.palette, label: 'Palette'),
            IconItem(icon: Icons.colorize, label: 'Colorize'),
            IconItem(icon: Icons.checkroom, label: 'Outfit'),
            IconItem(icon: Icons.brush, label: 'Brush'),
            IconItem(icon: Icons.gradient, label: 'Gradient'),
            IconItem(icon: Icons.auto_awesome, label: 'Generate'),
          ],
        ),
      ),
    );
  }
}

class IconItem extends StatelessWidget {
  final IconData icon;
  final String label;
  const IconItem({super.key, required this.icon, required this.label});

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        Icon(icon, size: 48, color: const Color(0xFF6B4F3B)),
        const SizedBox(height: 6),
        Text(label, style: const TextStyle(fontSize: 12)),
      ],
    );
  }
}
Hasil Tampilan
┌─────────────────────────────┐ │ ← Ikon Color Match │ ├─────────────────────────────┤ │ 🎨 🖌️ 👕 │ │ Palette Colorize Outfit │ │ 🖌 🌈 ✨ │ │ Brush Gradient Generate │ └─────────────────────────────┘
💡 Cari ikon lain di fonts.google.com/icons.

Buat kumpulan ikon sesuai aplikasi Color Match (contoh di atas).


5Button Widget

🎯 Tujuan: Siswa mampu membuat tombol interaktif dengan onPressed.

📚 Penjelasan

JenisKarakteristik
ElevatedButtonLatar penuh (paling menonjol)
OutlinedButtonBergaris tepi (sekunder)
TextButtonTanpa latar (tersier)

Semua punya onPressed → fungsi yang dijalankan saat ditekan. Jika null → tombol nonaktif.

💻 Kode Lengkap — Tombol "Generate Warna"

lib/materi5_page.dart
import 'package:flutter/material.dart';

class Materi5Page extends StatefulWidget {
  const Materi5Page({super.key});
  @override
  State<Materi5Page> createState() => _Materi5PageState();
}

class _Materi5PageState extends State<Materi5Page> {
  String hasilWarna = 'Belum ada warna';
  Color warnaTampil = const Color(0xFFD2B48C);

  void generateWarna() {
    final warna = [
      [const Color(0xFF8B7355), 'Taupe'],
      [const Color(0xFFA67B5B), 'Caramel'],
      [const Color(0xFF6B4F3B), 'Brown'],
      [const Color(0xFFD2B48C), 'Tan'],
      [const Color(0xFFCD853F), 'Peru'],
    ];
    final pilihan = (warna..shuffle()).first;
    setState(() {
      warnaTampil = pilihan[0] as Color;
      hasilWarna = pilihan[1] as String;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Generate Warna')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Container(
              width: 160,
              height: 160,
              decoration: BoxDecoration(
                color: warnaTampil,
                borderRadius: BorderRadius.circular(20),
              ),
            ),
            const SizedBox(height: 20),
            Text(
              hasilWarna,
              style: const TextStyle(fontSize: 22, fontWeight: FontWeight.bold),
            ),
            const SizedBox(height: 30),
            ElevatedButton.icon(
              onPressed: generateWarna,
              icon: const Icon(Icons.colorize),
              label: const Text('Generate Warna'),
            ),
            const SizedBox(height: 12),
            OutlinedButton(
              onPressed: () {
                setState(() {
                  hasilWarna = 'Belum ada warna';
                  warnaTampil = const Color(0xFFD2B48C);
                });
              },
              child: const Text('Reset'),
            ),
            const SizedBox(height: 12),
            TextButton(
              onPressed: () => ScaffoldMessenger.of(context).showSnackBar(
                const SnackBar(content: Text('Color Match Outfit v1.0')),
              ),
              child: const Text('Tentang Aplikasi'),
            ),
          ],
        ),
      ),
    );
  }
}
Hasil Tampilan
┌─────────────────────────────┐ │ ← Generate Warna │ ├─────────────────────────────┤ │ ╭──────────╮ │ │ │ WARNA │ 160×160 │ │ ╰──────────╯ │ │ Caramel │ │ │ │ [🎨 Generate Warna] │ ← diklik → warna berubah │ [ Reset ] │ │ [ Tentang Aplikasi ] │ → SnackBar di bawah └─────────────────────────────┘

Buat tombol Generate Warna yang menampilkan respons saat diklik (contoh di atas).


6Card Widget

🎯 Tujuan: Siswa mampu mengelompokkan informasi dalam bentuk kartu.

📚 Penjelasan

PropertiFungsi
elevationBayangan (semakin besar semakin "naik")
childIsi kartu
shapeBentuk (misal sudut melengkung)
marginJarak luar kartu

💻 Kode Lengkap — Kartu Rekomendasi Earth Tone

lib/materi6_page.dart
import 'package:flutter/material.dart';

class Materi6Page extends StatelessWidget {
  const Materi6Page({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: const Color(0xFFF5EFE6),
      appBar: AppBar(title: const Text('Rekomendasi Warna')),
      body: ListView(
        padding: const EdgeInsets.all(16),
        children: const [
          RekomendasiCard(
            warna: Color(0xFF8B7355),
            judul: 'Taupe',
            deskripsi: 'Cocok untuk kemeja formal, terkesan elegan.',
            icon: Icons.checkroom,
          ),
          RekomendasiCard(
            warna: Color(0xFFA67B5B),
            judul: 'Caramel',
            deskripsi: 'Hangat dan nyaman untuk outfit casual.',
            icon: Icons.brush,
          ),
          RekomendasiCard(
            warna: Color(0xFF6B4F3B),
            judul: 'Brown',
            deskripsi: 'Netral dan mudah dipadukan dengan warna lain.',
            icon: Icons.palette,
          ),
        ],
      ),
    );
  }
}

class RekomendasiCard extends StatelessWidget {
  final Color warna;
  final String judul;
  final String deskripsi;
  final IconData icon;
  const RekomendasiCard({
    super.key,
    required this.warna,
    required this.judul,
    required this.deskripsi,
    required this.icon,
  });

  @override
  Widget build(BuildContext context) {
    return Card(
      elevation: 4,
      margin: const EdgeInsets.only(bottom: 16),
      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Row(
          children: [
            Container(
              width: 60,
              height: 60,
              decoration: BoxDecoration(
                color: warna,
                borderRadius: BorderRadius.circular(12),
              ),
            ),
            const SizedBox(width: 16),
            Expanded(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Row(
                    children: [
                      Icon(icon, size: 18, color: warna),
                      const SizedBox(width: 6),
                      Text(
                        judul,
                        style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
                      ),
                    ],
                  ),
                  const SizedBox(height: 6),
                  Text(deskripsi, style: const TextStyle(fontSize: 14)),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}
Hasil Tampilan
┌─────────────────────────────┐ │ ← Rekomendasi Warna │ ├─────────────────────────────┤ │ ╭─────────────────────────╮ │ │ │ ███ 👕 Taupe │ │ │ │ ███ Cocok untuk kemeja │ │ │ │ formal, elegan. │ │ │ ╰─────────────────────────╯ │ │ ╭─────────────────────────╮ │ │ │ ███ 🖌 Caramel │ │ │ │ ███ Hangat untuk │ │ │ │ outfit casual. │ │ │ ╰─────────────────────────╯ │ └─────────────────────────────┘

Buat kartu rekomendasi warna pakaian bertema Earth Tone (contoh di atas).


7Scaffold Widget

🎯 Tujuan: Siswa memahami struktur dasar halaman aplikasi Flutter.

📚 Penjelasan

BagianFungsi
appBarBar atas (judul, tombol)
bodyIsi utama halaman
floatingActionButtonTombol melayang di kanan bawah
drawerMenu samping (opsional)
bottomNavigationBarNavigasi bawah (opsional)

Hubungan Scaffold & MaterialApp

MaterialApp = rumah besar aplikasi (tema, routing). Scaffold = kerangka per halaman di dalam rumah tersebut. Setiap halaman butuh Scaffold; MaterialApp cukup satu di root.

💻 Kode Lengkap — Kerangka Halaman Utama

lib/materi7_page.dart
import 'package:flutter/material.dart';

class Materi7Page extends StatelessWidget {
  const Materi7Page({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Color Match Outfit'),
        backgroundColor: const Color(0xFF6B4F3B),
        foregroundColor: Colors.white,
      ),
      body: const Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Icon(Icons.palette, size: 80, color: Color(0xFFA67B5B)),
            SizedBox(height: 16),
            Text(
              'Selamat Datang!',
              style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
            ),
            SizedBox(height: 8),
            Text(
              'Temukan paduan warna outfit terbaikmu.',
              textAlign: TextAlign.center,
              style: TextStyle(fontSize: 14),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          ScaffoldMessenger.of(context).showSnackBar(
            const SnackBar(content: Text('Fitur segera hadir!')),
          );
        },
        backgroundColor: const Color(0xFF6B4F3B),
        child: const Icon(Icons.add, color: Colors.white),
      ),
    );
  }
}
Hasil Tampilan
┌─────────────────────────────┐ │ Color Match Outfit (AppBar) ├─────────────────────────────┤ │ │ │ 🎨 │ │ Selamat Datang! │ │ Temukan paduan warna │ │ outfit terbaikmu. │ │ │ │ ╭───╮ │ │ │ + │ ←FAB │ ╰───╯ │ └─────────────────────────────┘

Buat kerangka halaman utama aplikasi Color Match (contoh di atas).


8SafeArea Widget

🎯 Tujuan: Siswa memahami pentingnya konten tidak tertutup notch / status bar.

📚 Penjelasan

SafeArea = bantalan otomatis agar konten tidak menabrak:

  • Status bar (jam, baterai di atas)
  • Notch / punch-hole (kamera depan)
  • Area navigasi bawah (gesture bar)

Hubungan SafeArea & Scaffold

Scaffold belum tentu memberi jarak aman, terutama body. SafeArea membungkus body supaya aman di semua perangkat.

⚠️ Dampak jika SafeArea tidak dipakai: Di HP ber-notch, teks/ikon bisa terpotong atau tertutup kamera.

💻 Kode Lengkap

lib/materi8_page.dart
import 'package:flutter/material.dart';

class Materi8Page extends StatelessWidget {
  const Materi8Page({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: const Color(0xFFF5EFE6),
      body: SafeArea(
        child: Column(
          children: [
            Container(
              width: double.infinity,
              padding: const EdgeInsets.all(20),
              color: const Color(0xFF6B4F3B),
              child: const Text(
                'Color Match Outfit',
                textAlign: TextAlign.center,
                style: TextStyle(
                  color: Colors.white,
                  fontSize: 22,
                  fontWeight: FontWeight.bold,
                ),
              ),
            ),
            Expanded(
              child: Center(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: const [
                    Icon(Icons.shield, size: 60, color: Color(0xFFA67B5B)),
                    SizedBox(height: 12),
                    Text(
                      'Konten aman dari notch & status bar',
                      textAlign: TextAlign.center,
                      style: TextStyle(fontSize: 16),
                    ),
                  ],
                ),
              ),
            ),
            Container(
              width: double.infinity,
              padding: const EdgeInsets.all(16),
              color: const Color(0xFFD2B48C),
              child: const Text(
                '© 2024 Color Match',
                textAlign: TextAlign.center,
                style: TextStyle(color: Colors.white),
              ),
            ),
          ],
        ),
      ),
    );
  }
}
Hasil Tampilan
┌─────────────────────────────┐ │ ⏰ 12:30 📶 🔋 │ ← status bar (aman) ├─────────────────────────────┤ │ Color Match Outfit │ ← header, tidak tertutup ├─────────────────────────────┤ │ │ │ 🛡️ │ │ Konten aman dari notch │ │ & status bar │ │ │ ├─────────────────────────────┤ │ © 2024 Color Match │ ← aman dari gesture bar └─────────────────────────────┘

Buat tampilan aplikasi yang kontennya tidak tertutup notch atau status bar (contoh di atas).


🏆Proyek Gabungan: Semua dalam Satu Aplikasi

Gabungkan 8 materi jadi satu aplikasi utuh. Ini adalah contoh main.dart final:

lib/main.dart
import 'package:flutter/material.dart';

void main() => runApp(const ColorMatchApp());

class ColorMatchApp extends StatelessWidget {
  const ColorMatchApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Color Match Outfit',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(primarySwatch: Colors.brown),
      home: const HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: const Color(0xFFF5EFE6),
      appBar: AppBar(  // Materi 7
        title: const Text('Color Match Outfit'),
        backgroundColor: const Color(0xFF6B4F3B),
        foregroundColor: Colors.white,
      ),
      body: SafeArea(  // Materi 8
        child: ListView(
          padding: const EdgeInsets.all(16),
          children: [
            // Materi 1: Text judul
            const Text(
              'Temukan Warna Outfitmu',
              style: TextStyle(
                fontSize: 24,
                fontWeight: FontWeight.bold,
                color: Color(0xFF6B4F3B),
              ),
            ),
            const SizedBox(height: 8),
            const Text('Pilih warna yang cocok untuk gayamu hari ini.'),
            const SizedBox(height: 16),

            // Materi 2: Image
            ClipRRect(
              borderRadius: BorderRadius.circular(16),
              child: Image.asset(
                'assets/images/outfit1.jpg',
                height: 200,
                width: double.infinity,
                fit: BoxFit.cover,
                errorBuilder: (_, __, ___) => Container(
                  height: 200,
                  color: Colors.brown.shade200,
                  child: const Center(child: Icon(Icons.image, size: 60)),
                ),
              ),
            ),
            const SizedBox(height: 20),

            // Materi 3: Container pilihan warna
            const Text('Pilihan Warna Earth Tone:',
                style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
            const SizedBox(height: 8),
            Wrap(
              spacing: 12,
              runSpacing: 12,
              children: const [
                _MiniColorBox(color: Color(0xFF8B7355)),
                _MiniColorBox(color: Color(0xFFA67B5B)),
                _MiniColorBox(color: Color(0xFF6B4F3B)),
                _MiniColorBox(color: Color(0xFFD2B48C)),
              ],
            ),
            const SizedBox(height: 20),

            // Materi 4: Icon
            const Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                Icon(Icons.palette, size: 40, color: Color(0xFF6B4F3B)),
                Icon(Icons.colorize, size: 40, color: Color(0xFF6B4F3B)),
                Icon(Icons.checkroom, size: 40, color: Color(0xFF6B4F3B)),
                Icon(Icons.brush, size: 40, color: Color(0xFF6B4F3B)),
              ],
            ),
            const SizedBox(height: 20),

            // Materi 6: Card
            Card(
              elevation: 4,
              shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
              child: const Padding(
                padding: EdgeInsets.all(16),
                child: Row(
                  children: [
                    Icon(Icons.auto_awesome, color: Color(0xFFA67B5B)),
                    SizedBox(width: 12),
                    Expanded(
                      child: Text(
                        'Kombinasi caramel + tan cocok untuk acara santai.',
                        style: TextStyle(fontSize: 14),
                      ),
                    ),
                  ],
                ),
              ),
            ),
            const SizedBox(height: 20),

            // Materi 5: Button
            ElevatedButton.icon(
              style: ElevatedButton.styleFrom(
                backgroundColor: const Color(0xFF6B4F3B),
                foregroundColor: Colors.white,
                padding: const EdgeInsets.symmetric(vertical: 14),
              ),
              onPressed: () {
                ScaffoldMessenger.of(context).showSnackBar(
                  const SnackBar(content: Text('Warna berhasil di-generate!')),
                );
              },
              icon: const Icon(Icons.colorize),
              label: const Text('Generate Warna'),
            ),
          ],
        ),
      ),
    );
  }
}

class _MiniColorBox extends StatelessWidget {
  final Color color;
  const _MiniColorBox({required this.color});

  @override
  Widget build(BuildContext context) {
    return Container(
      width: 60,
      height: 60,
      decoration: BoxDecoration(
        color: color,
        borderRadius: BorderRadius.circular(12),
      ),
    );
  }
}

📋Rangkuman Cepat

1
Text
Menampilkan tulisan · TextStyle
2
Image
Menampilkan gambar · BoxFit
3
Container
Wadah & styling · BoxDecoration
4
Icon
Simbol visual · Icons.palette
5
Button
Aksi interaktif · onPressed
6
Card
Kelompok info · elevation
7
Scaffold
Kerangka halaman · AppBar
8
SafeArea
Amankan notch · bungkus body

💡Tips Belajar untuk Pemula

  • Ubah satu properti, lihat hasilnya. Coba ganti fontSize 32 → 40, lihat perubahannya.
  • Hot Reload. Tekan r di terminal untuk melihat perubahan tanpa restart.
  • Baca error dengan teliti. Flutter memberi pesan error yang jelas (baris & penyebab).
  • Gunakan const di widget yang tidak berubah untuk performa lebih baik.
  • Konsisten urutan. Kerjakan materi 1 → 8 berurutan, karena setiap materi saling membangun.
🚀 Selamat belajar Flutter! Semoga materi ini membantumu memahami dasar-dasar widget Flutter.

  • Lebih baru

    8 Widget Flutter untuk Pemula :

Posting Komentar

0 Komentar

Posting Komentar (0)
3/related/default