textstylingwidgetPemula4 mnt baca

Text & Styling Teks

Widget Text, TextStyle, RichText, dan ellipsis untuk teks panjang.

Analogi: Papan Menu Warung

Bayangkan papan menu di warung kopi. Nama menu ditulis besar dan tebal supaya terbaca dari jauh, harganya ditulis dengan warna mencolok supaya cepat ditemukan mata, dan catatan kaki ditulis kecil miring. Isi tulisannya (kata-katanya) terpisah dari cara menampilkannya (besar, warna, tebal). Di Flutter pemisahannya persis begitu: widget Text menyimpan apa yang ditulis, sedangkan TextStyle mengatur bagaimana ia ditampilkan.

Kenapa dipisah? Karena satu gaya sering dipakai ulang di banyak tempat. Judul halaman di sepuluh layar berbeda sebaiknya memakai gaya yang sama. Kalau gaya menempel pada tiap teks satu per satu, mengubah ukuran judul berarti mengedit sepuluh tempat.

Kenapa TextStyle Terpisah dari Text?

Pemisahan ini menyelesaikan tiga masalah sekaligus. Pertama, konsistensi: kamu bisa mendefinisikan gaya sekali (atau lewat tema) lalu memakainya di mana-mana. Kedua, pewarisan: Text otomatis mewarisi gaya dari DefaultTextStyle terdekat di atasnya, jadi teks di dalam sebuah kartu bisa mengikuti gaya kartu tanpa ditulis ulang. Ketiga, komposisi: RichText bisa menggabungkan banyak TextSpan dengan gaya berbeda dalam satu baris, seperti harga coret dan harga diskon yang berdampingan.

Contoh 1: TextStyle Dasar yang Sering Dipakai

dart
const Text(
  'Kopi Tubruk',
  style: TextStyle(
    fontSize: 20,
    fontWeight: FontWeight.bold,
    color: Colors.brown,
    letterSpacing: 1.2,
    height: 1.5,
  ),
  textAlign: TextAlign.center,
)

Properti yang paling sering kamu sentuh: fontSize (ukuran), fontWeight (ketebalan, dari w100 sampai w900 atau FontWeight.bold), color, letterSpacing (jarak antar huruf), dan height (jarak antar baris, dalam kelipatan ukuran font). textAlign mengatur perataan, tetapi hanya berpengaruh kalau teksnya punya ruang horizontal lebih lebar dari isi tulisannya.

Contoh 2: Kartu Harga yang Realistis

Contoh yang lebih realistis: kartu produk dengan nama, harga coret, harga diskon, dan deskripsi yang dipotong otomatis kalau terlalu panjang.

dart
Card(
  child: Padding(
    padding: const EdgeInsets.all(16),
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        const Text(
          'Kopi Susu Gula Aren',
          style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
        ),
        const SizedBox(height: 4),
        RichText(
          text: const TextSpan(
            style: TextStyle(fontSize: 14, color: Colors.black87),
            children: [
              TextSpan(
                text: 'Rp20.000 ',
                style: TextStyle(
                  decoration: TextDecoration.lineThrough,
                  color: Colors.grey,
                ),
              ),
              TextSpan(
                text: 'Rp15.000',
                style: TextStyle(
                  fontWeight: FontWeight.bold,
                  color: Colors.red,
                ),
              ),
            ],
          ),
        ),
        const SizedBox(height: 4),
        const Text(
          'Kopi susu dengan gula aren asli, diseduh fresh setiap pagi '
          'menggunakan biji kopi pilihan dari dataran tinggi.',
          maxLines: 2,
          overflow: TextOverflow.ellipsis,
          style: TextStyle(fontSize: 13, color: Colors.black54),
        ),
      ],
    ),
  ),
)

Perhatikan tiga teknik dalam satu kartu: Text biasa untuk judul, RichText untuk harga campuran, dan maxLines + ellipsis supaya deskripsi panjang tidak merusak layout.

Menangani Teks Panjang

Teks dari data nyata (nama produk, komentar user) panjangnya tidak bisa ditebak. Tanpa pengaman, teks yang kepanjangan menyebabkan error overflow: layar bergaris kuning-hitam yang terkenal itu. Kombinasi pengamannya:

dart
const Text(
  'Nama produk yang sangat panjang dan tidak muat dalam satu baris kartu',
  maxLines: 2,
  overflow: TextOverflow.ellipsis,
  softWrap: true,
)

maxLines: 2 membatasi maksimal dua baris, overflow: TextOverflow.ellipsis memotong sisanya dengan "...", dan softWrap: true (nilai default) mengizinkan pindah baris secara natural. Alternatif TextOverflow.fade membuat teks memudar di ujung, cocok untuk efek visual yang halus.

Catatan teknis: RichText tidak mewarisi DefaultTextStyle seperti Text biasa, jadi selalu tentukan style dasarnya di TextSpan paling luar. Kalau tidak, teksmu bisa tampil dengan gaya default yang tidak kamu harapkan (dan di dark mode bisa jadi tidak terbaca).

Kesalahan umum pemula

1. Hardcoding gaya di setiap Text, bukan memakai tema.

dart
// SALAH: mengubah ukuran judul berarti mengedit setiap layar satu per satu
const Text('Judul', style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold))

// BENAR: cukup ubah di ThemeData, semua judul ikut berubah
Text('Judul', style: Theme.of(context).textTheme.headlineSmall)

Flutter sudah menyediakan skala tipografi siap pakai (headlineSmall, titleMedium, bodyLarge, dan seterusnya) yang otomatis mengikuti tema terang/gelap.

2. Teks overflow di dalam Row karena tidak dibungkus Expanded.

dart
// SALAH: teks panjang mendorong Row hingga overflow
Row(children: [Icon(Icons.info), Text('Pesan error yang sangat panjang...')])

// BENAR: Expanded memberi tahu teks berapa ruang yang tersedia
Row(
  children: [
    const Icon(Icons.info),
    const Expanded(child: Text('Pesan error yang sangat panjang...')),
  ],
)

Text butuh tahu batas lebarnya sebelum bisa membungkus atau memotong teks. Di dalam Row, batas itu tidak ada kecuali kamu memberikannya lewat Expanded atau Flexible.

3. Lupa style dasar di RichText. Seperti catatan di atas, RichText yang TextSpan luarnya tanpa style akan memakai gaya default mentah: ukuran 14, warna mengikuti platform, dan tidak mengikuti tema aplikasimu. Selalu isi style di span terluar.

4. Memakai banyak Text bersebelahan untuk satu kalimat bergaya campuran. Misalnya tiga widget Text dalam Row untuk "Total: Rp50.000" dengan sebagian tebal. Selain ribet, spasi antar katanya jadi sulit diatur dan bisa pecah baris di tempat yang aneh. Satu RichText dengan beberapa TextSpan adalah alat yang tepat untuk kasus ini.

Tantangan

Harga coret dan tebal

Buat RichText yang menampilkan 'Rp100.000' dicoret abu-abu, diikuti ' Rp75.000' tebal berwarna merah, dalam satu baris.