İçeriğe geç / Skip to content / Zum Inhalt

Flutter: SizedBox ile Boyutlandırma ve Boşluk

Ahmet Balaman

Son güncelleme:

5 dk okuma

FlutterSizedBoxLayoutSpacingConstraintsWidget
Flutter: SizedBox ile Boyutlandırma ve Boşluk

SizedBox, çocuğuna sabit bir genişlik ve/veya yükseklik dayatan ya da çocuğu yokken belirtilen boyutta boş bir kutu olarak duran hafif bir widget'tır. İki metin arasındaki 16 piksel, tam genişlikte bir buton, 40x40'lık bir ikon kutusu, koşul sağlanmadığında "hiçbir şey" göstermek: hepsi bu widget'la yapılır. Bu yazıda kurucularını, Container ile farkını, verdiğiniz boyutun bazen neden yok sayıldığını ve en sık yapılan hataları anlatıyorum.

Temel Kullanım

SizedBox(
  width: 200,
  height: 100,
  child: Container(
    color: Colors.blue,
    child: const Center(child: Text('200x100 kutu')),
  ),
)

Yalnızca tek bir eksen de verebilirsiniz: SizedBox(width: 150, child: ElevatedButton(...)) butonun genişliğini sabitler, yüksekliğini butonun kendisine bırakır. Verilmeyen eksende SizedBox saydamdır; çocuğu o eksende parent'tan gelen kısıtlamayla ölçülür.

Boşluk Oluşturma

En yaygın kullanım, çocuksuz bir SizedBox'ı kardeş widget'lar arasına ayraç olarak koymaktır. Column içinde height, Row içinde width verilir:

Column(
  children: [
    const Text('Birinci metin'),
    const SizedBox(height: 16),
    const Text('İkinci metin'),
    const SizedBox(height: 24),
    FilledButton(onPressed: () {}, child: const Text('Buton')),
  ],
)

Boşluk değerleri sabit olduğu için const SizedBox(height: 16) yazın; aynı nesne her build'de yeniden kullanılır. Boşluğu Padding ile vermek de mümkündür ama Padding bir çocuğu sarar, kardeşler arasında durmaz; bu ayrımı Padding yazısında ayrıntılı anlattım.

İsimli Kurucular

SizedBox'ın dört yardımcı kurucusu vardır:

  • SizedBox.expand(child:): Parent'ın verdiği maksimum genişlik ve yüksekliği kaplar. width: double.infinity, height: double.infinity yazmanın kısa yoludur; parent'ın bir ekseni sınırsızsa çalışmaz.
  • SizedBox.shrink(): 0x0 boyutunda boş kutu. Koşullu olarak "hiçbir şey" döndürmenin standart yoludur ve Container() yazmaktan daha hafiftir.
  • SizedBox.square(dimension: 40): Kare kutu; avatar, ikon arka planı, yükleme göstergesi gibi eşit kenarlı öğelerde okunabilirliği artırır.
  • SizedBox.fromSize(size: Size(120, 40)): Elinizde zaten bir Size nesnesi varsa kullanılır.

SizedBox.expand tüm alanı kaplar, shrink sıfır boyuttadır, square kare üretir, fromSize hazır bir Size nesnesini kullanır

// Koşula göre bir rozet ya da hiçbir şey
unreadCount > 0 ? Badge(label: Text('$unreadCount')) : const SizedBox.shrink()

Bir children listesi içindeyseniz üçlü operatör yerine collection-if daha temizdir: if (unreadCount > 0) Badge(...). shrink(), tek bir child parametresine bir widget vermek zorunda olduğunuz yerler içindir.

Verdiğiniz Boyut Neden Yok Sayılıyor?

SizedBox içeride bir ConstrainedBox gibi çalışır: istediğiniz boyutu parent'tan gelen kısıtlamalarla birleştirir ve parent'ın kısıtlaması her zaman kazanır. Kısıtlamaların aşağı, boyutların yukarı aktığı bu modeli Flutter'ın "Understanding constraints" rehberi baştan sona örneklerle anlatıyor. Parent "tam olarak 360 piksel genişlikte ol" diyorsa (tight constraint), siz width: 100 yazsanız da kutu 360 olur.

Bunu en çok üç yerde görürsünüz:

// 1. Scaffold body: SizedBox tüm ekranı kaplar, 100x100 olmaz
Scaffold(body: SizedBox(width: 100, height: 100, child: ...))

// 2. Expanded içinde: genişlik Expanded'ın verdiği alandır
Row(children: [Expanded(child: SizedBox(width: 100, child: ...))])

// 3. crossAxisAlignment: stretch: genişlik Column kadar olur
Column(crossAxisAlignment: CrossAxisAlignment.stretch, children: [SizedBox(width: 100, ...)])

Çözüm her seferinde aynıdır: SizedBox'ı tight kısıtlamayı gevşeten bir widget'ın içine alın. Center, Align veya UnconstrainedBox, çocuğuna "istediğin kadar küçük olabilirsin" der; o zaman SizedBox'ın boyutu geçerli olur. Flutter'ın "kısıtlamalar aşağı iner, boyutlar yukarı çıkar" kuralını widget ağacı ve layout girişinde bulabilirsiniz.

SizedBox ve Container

Container da width ve height alır, ama Container bir "her şeyi yapan" sarmalayıcıdır: verdiğiniz parametrelere göre içeride Padding, DecoratedBox, ConstrainedBox, Align gibi widget'ları kendisi oluşturur. Yalnızca boyut istiyorsanız SizedBox daha az widget üretir ve niyetinizi daha net söyler. Renk, kenarlık, gölge veya köşe yuvarlatma gerekiyorsa Container (ya da doğrudan DecoratedBox) kullanın. Boş bir Container, parent sınırlıysa parent kadar büyür; boş bir SizedBox ise verdiğiniz boyutta kalır. Bu yüzden "boşluk" için Container değil SizedBox doğru araçtır.

Ne Zaman Kullanılır, Ne Zaman Kullanılmaz?

SizedBox kullanın:

  • Kardeşler arası sabit boşluk için (const SizedBox(height: 16)).
  • Bir çocuğa sabit boyut vermek için (tam genişlik buton, 48 piksellik satır yüksekliği).
  • Koşullu olarak hiçbir şey göstermek için (SizedBox.shrink()).

Başka bir araca geçin:

  • Kalan alanı doldurmak istiyorsanız SizedBox.expand değil Expanded kullanın; Row ve Column içinde çalışan odur. Farkı Expanded yazısında anlattım.
  • Esnek boşluk ("bu ikisini iki uca it") için Spacer ya da mainAxisAlignment: spaceBetween.
  • Boyutu bir aralıkta tutmak istiyorsanız (en az 48, en fazla 200) ConstrainedBox.
  • Çok sayıda aynı boşluk için güncel Flutter sürümlerinde Row ve Column'un spacing parametresi; on tane SizedBox(height: 8) yerine tek satır.

Sık Yapılan Hatalar

1. Row içinde height, Column içinde width vermek

Belirti: Boşluk hiç görünmüyor. SizedBox(height: 16) Row'un ana ekseninde sıfır genişliktedir; yatayda hiçbir şeyi ayırmaz. Row'da width, Column'da height kullanın.

2. Row içinde double.infinity genişlik

Belirti: BoxConstraints forces an infinite width. Row çocuklarına sınırsız genişlik verir; SizedBox(width: double.infinity) bu sınırsızlığı kabul etmeye çalışır ve layout patlar.

// Hatalı
Row(children: [SizedBox(width: double.infinity, child: Text('x'))])

// Doğru: kalan alanı Expanded alır
Row(children: [Expanded(child: Text('x'))])

double.infinity, yalnızca parent'ın o eksende sınırlı olduğu yerlerde (Scaffold body, Column'un yatay ekseni) anlamlıdır.

3. Boyutun yok sayılmasını Flutter hatası sanmak

Belirti: SizedBox(width: 100) yazdınız, kutu ekran genişliğinde çıktı. Yukarıda anlattığım gibi parent'ın tight kısıtlaması kazanmıştır. Kutuyu Center veya Align içine alın:

Scaffold(
  body: Center(
    child: SizedBox(width: 100, height: 100, child: ColoredBox(color: Colors.blue)),
  ),
)

4. shrink() yerine boş Container

Belirti: Görünmez olması gereken yer beklenmedik şekilde alan kaplıyor. Boş Container() sınırlı bir parent'ta parent kadar büyür. const SizedBox.shrink() her zaman 0x0'dır.

Mini Senaryo: Profil Başlığı

Bir ayarlar ekranının üstündeki profil bloğunu düşünün: sabit boyutlu avatar, isim ve e-posta, koşullu "doğrulanmadı" rozeti ve tam genişlikte bir düzenle butonu.

class ProfileHeader extends StatelessWidget {
  const ProfileHeader({super.key, required this.name, required this.email, required this.verified});

  final String name;
  final String email;
  final bool verified;

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(16),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          Row(
            children: [
              SizedBox.square(
                dimension: 56,
                child: CircleAvatar(child: Text(name.substring(0, 1))),
              ),
              const SizedBox(width: 16),
              Expanded(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(name, style: Theme.of(context).textTheme.titleMedium),
                    const SizedBox(height: 4),
                    Text(email, overflow: TextOverflow.ellipsis),
                  ],
                ),
              ),
              const SizedBox(width: 8),
              verified
                  ? const Icon(Icons.verified, color: Colors.green)
                  : const SizedBox.shrink(),
            ],
          ),
          const SizedBox(height: 16),
          SizedBox(
            height: 48,
            child: OutlinedButton(onPressed: () {}, child: const Text('Profili Düzenle')),
          ),
        ],
      ),
    );
  }
}

SizedBox.square avatarı 56x56'ya sabitler; SizedBox(width: 16) ve height: 4 ayraçlardır; Expanded metin bloğunun kalan genişliği almasını ve uzun e-postanın kırpılmasını sağlar. Butonun SizedBox'ına yalnızca height verdim: genişlik, Column'un crossAxisAlignment: stretch ayarından geliyor, yani width: double.infinity yazmaya gerek yok. Rozet için SizedBox.shrink() kullandım; Row'un children listesinde if (verified) const Icon(...) de aynı işi görürdü.

Sık Sorulan Sorular

SizedBox ile Container arasındaki fark nedir?

SizedBox yalnızca boyut verir; Container ise renk, padding, kenarlık ve hizalama için içeride ek widget'lar oluşturur. Sadece boyut veya boşluk gerekiyorsa SizedBox daha hafiftir ve niyeti daha net gösterir.

SizedBox'a verdiğim genişlik neden uygulanmıyor?

Parent'ın kısıtlaması SizedBox'ın isteğinden önce gelir. Scaffold body, Expanded veya CrossAxisAlignment.stretch gibi tight kısıtlama veren yerlerde kutu parent kadar olur; SizedBox'ı Center veya Align içine alarak kısıtlamayı gevşetin.

SizedBox.shrink() ile boş Container() aynı mı?

Hayır. SizedBox.shrink() her zaman 0x0'dır; boş Container() sınırlı bir parent'ta parent'ın tamamını kaplar. Koşullu "hiçbir şey gösterme" için shrink kullanın ya da listelerde collection-if yazın.

SizedBox.expand ile Expanded aynı işi mi yapar?

Hayır. SizedBox.expand parent'ın verdiği maksimum alanı kaplar ve Row/Column dışında da çalışır; Expanded yalnızca Row, Column ve Flex içinde kardeşlerden arta kalan alanı paylaştırır. Row içinde SizedBox.expand sınırsız genişlik hatası verir.

Yorumlar