---
title: Değiştiriciler
source: 'https://academia.sh/tr/kurslar/compose/degistiriciler'
course: 'Jetpack Compose ile Arayüz'
language: tr
updated: '2026-10-21T05:02:38+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Değiştirici zincirini iç içe sarmalayıcı düğümler olarak okur'
    - 'Aynı iki değiştiricinin sırası değişince son genişliğin değiştiğini ölçer'
    - 'Arka planın kapladığı alanın sıraya bağlı olduğunu gösterir'
    - 'Aynı kısıtın sıraya göre aşağı ya da derin gittiğini sınıflandırır'
---

# Değiştiriciler

Değiştirici zincirinde sıranın anlamı ve dıştaki değiştiricinin kısıtının içeriğe hangi yönde ulaştığının ölçümü.

Önceki derste bir sütun, kendisine verilen genişliği çocuklarına iletti ve kısıtın ebeveynden çocuğa, yani aşağı gittiği görüldü. Bu ders aynı kısıtın bir düğümden değil, bir zincirden geçişine bakar. Bir bileşen işlevinin `modifier` parametresine verilen değiştirici zinciri (`Modifier`) boyut, boşluk, arka plan ve tıklama davranışı ekler. Zincir soldan sağa yazılır ve sıra anlam taşır: aynı iki değiştirici ters sırada başka bir sonuç verir.

Bu sonucun nedeni, zincirdeki her değiştiricinin kendisinden sonra gelenleri sarmasıdır. Dıştaki değiştirici kısıtı alır, değiştirir ve içtekine verir; içtekinden dönen ölçüyü kendi payıyla büyütür ya da sınırlar. Ölçülecek şey, bu sarmalamanın arayüz ağacında nasıl göründüğüdür.

```kotlin
// Direction.kt — bir verinin arayuz agacinda hangi yone gittigini siniflandirir
class Tree(private val parentOf: Map<String, String>) {
    fun contains(node: String): Boolean = node in parentOf.keys || node in parentOf.values
    fun parent(node: String): String? = parentOf[node]
    fun ancestors(node: String): List<String> {
        val chain = mutableListOf<String>()
        var current = parentOf[node]
        while (current != null) {
            chain.add(current)
            current = parentOf[current]
        }
        return chain
    }
}

class Move(val label: String, val from: String, val to: String, tree: Tree) {
    val direction: String = when {
        !tree.contains(from) || !tree.contains(to) -> "dis"
        to in tree.ancestors(from) -> "yukari"
        tree.parent(to) == from -> "asagi"
        from in tree.ancestors(to) -> "derin"
        else -> error("akrabasiz: $from ve $to")
    }

    fun describe() {
        println("$label: kimden=$from | kime=$to -> $direction")
    }
}

fun countDirections(moves: List<Move>) {
    for (name in listOf("asagi", "yukari", "derin", "dis")) {
        println("$name: ${moves.count { it.direction == name }}")
    }
}
```

## Zincir ve Sıra

Aşağıdaki parça iki zincir kurur. İlkinde boyut boşluktan önce gelir, ikincisinde sonra. Üçüncü örnek, tıklama alanının boşluğu kapsayıp kapsamadığını sıraya göre değiştiren zincirdir.

```kotlin
// Platform kodu: sirasi anlam tasiyan zincirler
@Composable
fun Chains() {
    Box(Modifier.size(200.dp).padding(16.dp).background(Color.LightGray))
    Box(Modifier.padding(16.dp).size(200.dp).background(Color.LightGray))
    Text(
        text = "Open",
        modifier = Modifier.fillMaxWidth().clickable { open() }.padding(16.dp),
    )
}
```

İlk iki `Box` aynı üç değiştiriciyi taşır, ama sırayı farklıdır. `size(200.dp)` önce gelirse düğümün toplam genişliği 200'dür ve boşluk bu 200'ün içinden ayrılır. `padding(16.dp)` önce gelirse içerik 200 genişliğinde olur ve boşluk onun dışına eklenir. Üçüncü örnekte `clickable`, `padding`'den önce olduğu için tıklanabilir alan boşluğu da kapsar; sıra tersine çevrilirse yalnız içeriği kapsar.

Platformun kuralı şudur: zincirin ilk değiştiricisi kısıtı alır, onu işleyip ikinciye verir. Zincirin sonunda içerik, dar kısıtlarla ölçülür. Model bu kuralı kurar. Model, platformun kendisi değildir. Yardımcı dosya üç değiştirici tanır: `SizeMod` genişliği kısıtlar, `PaddingMod` her iki yandan boşluk ayırır, `BackgroundMod` kapladığı alanı kaydeder. İçerik, kendisine verilen en büyük genişliği alır; bu bir modelleme varsayımıdır. Ayrıca `wrapChain` işlevi, zinciri arayüz ağacına çevirir: ilk değiştirici ebeveynin çocuğudur, sonraki her değiştirici bir öncekinin çocuğudur, içerik en içtedir.

```kotlin
// Chain.kt — degistirici zincirinin olcusu (modelin hesabi)
sealed interface Mod
class SizeMod(val width: Int) : Mod
class PaddingMod(val amount: Int) : Mod
object BackgroundMod : Mod

class Measured(val total: Int, val content: Int, val painted: Int?)

fun measureChain(chain: List<Mod>, min: Int, max: Int): Measured {
    if (chain.isEmpty()) return Measured(max, max, null)
    val rest = chain.drop(1)
    return when (val mod = chain.first()) {
        is SizeMod -> {
            val fixed = mod.width.coerceIn(min, max)
            val inner = measureChain(rest, fixed, fixed)
            Measured(fixed, inner.content, inner.painted)
        }
        is PaddingMod -> {
            val inner = measureChain(rest, maxOf(0, min - 2 * mod.amount), maxOf(0, max - 2 * mod.amount))
            Measured((inner.total + 2 * mod.amount).coerceIn(min, max), inner.content, inner.painted)
        }
        BackgroundMod -> {
            val inner = measureChain(rest, min, max)
            Measured(inner.total, inner.content, inner.total)
        }
    }
}

class Wrapped(val tree: Tree, val nodes: List<String>)

fun wrapChain(chain: List<Mod>, parent: String): Wrapped {
    val nodes = chain.map {
        when (it) {
            is SizeMod -> "Size"
            is PaddingMod -> "Padding"
            BackgroundMod -> "Background"
        }
    } + "Content"
    val parentOf = nodes.indices.associate { nodes[it] to (if (it == 0) parent else nodes[it - 1]) }
    return Wrapped(Tree(parentOf), nodes)
}
```

## Boyut Boşluğun İçinde

İlk ölçüm `size(200)` ve ardından `padding(16)` zincirini kurar. Ebeveyn, en fazla 360 genişliğinde bir kısıt verir. Ağaç `Row` altında `Size`, onun altında `Padding`, onun altında `Content` olur. Her kısıt bir sarmalayıcıdan, hemen içindekine geçer.

```kotlin
// Main.kt — boyut once, bosluk sonra
fun main() {
    val chain = listOf(SizeMod(200), PaddingMod(16))
    val wrapped = wrapChain(chain, "Row")
    val measured = measureChain(chain, 0, 360)
    println("toplam=${measured.total} icerik=${measured.content}")
    val moves = listOf(
        Move("kisit-boyut", wrapped.nodes[0], wrapped.nodes[1], wrapped.tree),
        Move("kisit-bosluk", wrapped.nodes[1], wrapped.nodes[2], wrapped.tree),
    )
    for (move in moves) {
        move.describe()
    }
    countDirections(moves)
}
```

```text
toplam=200 icerik=168
kisit-boyut: kimden=Size | kime=Padding -> asagi
kisit-bosluk: kimden=Padding | kime=Content -> asagi
asagi: 2
yukari: 0
derin: 0
dis: 0
```

Düğümün toplam genişliği 200, içerik 168. Boşluk 200'ün içinden ayrıldı: her yandan 16, toplam 32. İki kısıt hareketi de aşağıdır, çünkü her biri sarmalayıcıdan hemen içindeki düğüme gider. Kısıt, dıştaki değiştiricinin kısıtını doğrudan sarmaladığına verdiği hareket olarak sınıflanır: aşağı.

**AD1.** Model `size` değiştiricisini tek bir genişlikle sınırlar ve `coerceIn` ile kısıtın içinde tutar. Platformdaki `requiredSize` gibi kısıtı aşabilen değiştiriciler ölçülmedi.

## Sıra Değişince Son Genişlik

Şimdi iki değiştiricinin sırası ters çevrilir: önce boşluk, sonra boyut. Ebeveynin kısıtı aynıdır. Fark, kısıtın önce boşluğa ulaşmasıdır; boşluk kısıtı daraltır, boyut daralmış kısıtın içinde 200'ü seçer ve boşluk bu 200'ün dışına eklenir.

```kotlin
// Main.kt — iki sirada son genislik
fun main() {
    val orders = listOf(
        "boyut-bosluk" to listOf(SizeMod(200), PaddingMod(16)),
        "bosluk-boyut" to listOf(PaddingMod(16), SizeMod(200)),
    )
    for ((name, chain) in orders) {
        val measured = measureChain(chain, 0, 360)
        println("$name: toplam=${measured.total} icerik=${measured.content}")
    }
}
```

```text
boyut-bosluk: toplam=200 icerik=168
bosluk-boyut: toplam=232 icerik=200
```

Aynı iki değiştirici, aynı kısıt; toplam genişlik 200'e karşı 232, içerik 168'e karşı 200. Zincirin sırası, değerin hangi sarmalayıcıda eklendiğini belirler. Bunlar modelin hesabıdır. Sıranın ağaçtaki karşılığı, son bölümde ölçülür.

**AD2.** Ebeveyn kısıtı 360 olarak sabitlendi. Kısıtın alt sınırı sıfır alındı; alt sınırı sıfırdan büyük kısıtlar bu derste ölçülmedi.

## Kısıt İçe, Ölçü Dışa

Zincirin okunuşunda iki yön vardır ve ikisi de aynı zincirde yaşar. Kısıt dıştan içe iner: her halka kısıtı işleyip bir içtekine verir. Ölçü içten dışa döner: içerik boyutunu bildirir, her halka bu boyuta kendi payını ekler ya da çıkarır ve bir dıştakine bildirir. Yukarıdaki ilk ölçümde içerik 168 genişliğinde döndü, `Padding` buna 32 ekledi ve `Size` 200'ü bildirdi. İkinci sırada aynı dönüş 168 yerine 200 ile başladı ve 232 ile bitti.

Bu ayrım, iki yaygın yanlış okumayı önler. Birincisi, `size` değiştiricisinin her zaman son boyutu kesinleştirdiği düşüncesidir. `size`, yalnız kısıtı sabitler; sabitlediği değer hâlâ ondan önce gelen halkaların kısıtının içinde kalır. Model bunu `coerceIn` ile kurdu. Platformda kısıtı aşabilen ayrı bir değiştirici de vardır, `requiredSize`; bu ders onu ölçmedi. İkincisi, sıranın yalnız görünümü etkilediği düşüncesidir. Sıra, hangi halkanın hangi kısıtı gördüğünü belirler; görünüm bunun sonucudur.

Zincirin ağaçtaki yeri de ayrıca not edilmelidir. Platformda her halkanın ayrı bir arayüz düğümü olduğu varsayılmaz. Model ise her halkayı bir düğüm sayar; çünkü ölçülen ilişki, hangi halkanın hangi halkadan önce kısıt aldığıdır. Bu bir basitleştirmedir ve sonuçları, kısıtın geçtiği sırayı doğru yansıttığı ölçüde geçerlidir.

**AD3.** Model her değiştiriciyi bir düğüm sayar. Platformun değiştirici zincirini kendi içinde nasıl temsil ettiği bu derste ölçülmedi.

## Arka Plan Sırayı İzler

Arka plan, kendi düğümünün kapladığı alanı boyar; yani sarmaladığı zincirin toplamı kadarını. `padding` arka plandan önce gelirse arka plan boşluğun içinde kalır. Arka plan önce gelirse boşluğu da boyar.

```kotlin
// Main.kt — arka planin kapladigi alan
fun main() {
    val orders = listOf(
        "bosluk-arkaplan" to listOf(PaddingMod(16), BackgroundMod),
        "arkaplan-bosluk" to listOf(BackgroundMod, PaddingMod(16)),
    )
    for ((name, chain) in orders) {
        val measured = measureChain(chain, 0, 360)
        println("$name: boyanan=${measured.painted} icerik=${measured.content}")
    }
}
```

```text
bosluk-arkaplan: boyanan=328 icerik=328
arkaplan-bosluk: boyanan=360 icerik=328
```

İçerik iki durumda da 328 genişliğinde. Boyanan alan ise 328'e karşı 360. Bu, `background` değiştiricisinin tek başına bir genişliği olmadığını gösterir: genişliği, zincirde kendisinden sonra gelenlerin toplamıdır. Tıklama alanı da aynı mantıkla çalışır: `clickable`, sarmaladığı zincirin kapladığı alanı dinler.

**AD4.** Model boyanan alanı yalnız genişlik olarak ölçer; yükseklik ve köşe yuvarlama gibi şekil bilgisi modelde yoktur. Tıklama alanı da bu derste ölçülmedi, yalnız arka planla aynı mantığı izlediği söylendi.

## Sınırlayıcı Ölçüm

Dersin yönü, sıranın yönü değiştirip değiştirmediği sorusuyla belirlenir. `Size`'ın kısıtı iki sırada da içeriğe ulaşır. Ama bir sırada `Padding` onun hemen içindedir, diğer sırada `Size` içeriği doğrudan sarar. Ölçüm, her iki sırada `Size`'tan `Content`'e giden kısıt hareketini sınıflandırır.

```kotlin
// Main.kt — ayni kisitin iki siradaki yonu
fun main() {
    val orders = listOf(
        "boyut-bosluk" to listOf(SizeMod(200), PaddingMod(16)),
        "bosluk-boyut" to listOf(PaddingMod(16), SizeMod(200)),
    )
    val moves = mutableListOf<Move>()
    for ((name, chain) in orders) {
        val wrapped = wrapChain(chain, "Row")
        moves.add(Move("boyut-icerige-$name", "Size", wrapped.nodes.last(), wrapped.tree))
    }
    for (move in moves) {
        move.describe()
    }
    countDirections(moves)
}
```

```text
boyut-icerige-boyut-bosluk: kimden=Size | kime=Content -> derin
boyut-icerige-bosluk-boyut: kimden=Size | kime=Content -> asagi
asagi: 1
yukari: 0
derin: 1
dis: 0
```

Aynı `Size` kısıtı, `boyut-bosluk` sırasında `Content`'e derin ulaşır, çünkü araya `Padding` girmiştir. `bosluk-boyut` sırasında `Size` içeriği doğrudan sarar ve kısıt aşağı gider. Değiştirici aynı, kısıt aynı; sıra değişince araya giren sarmalayıcı yönü değiştirir. Zincirin her halkası kısıtı hemen içindekine verir; bu hareketler aşağıdır. Derin, araya giren halkaların atlandığı durumdur ve onu yalnız sıra doğurur. Kısıtın zincir boyunca asıl yolu halka halka iner, bu yüzden dersin yönü: **aşağı**.

**AD5.** Model yalnız bir kısıt ve iki sıra için yönü sınıflandırır. Üç ya da daha fazla halkalı zincirde atlanan halka sayısı arttıkça hareket yine derindir, ama bu sayı ölçülmedi.

## Özet

- Bu dersin yönü: aşağı. Kısıt, zincirde sarmalayan halkadan sarmalanana doğrudan iner.
- Değiştirici zinciri, her halkası kendisinden sonrakini saran iç içe düğümlerdir.
- Dıştaki değiştiricinin kısıtı, doğrudan sarmaladığına aşağı gider.
- Aynı iki değiştiricinin sırası değişince son genişlik değişir; boşluk boyutun içinde ya da dışında kalır.
- Arka planın kapladığı alan, kendisinden sonra gelen zincirin toplamıdır.

## Sonraki Adım

Değiştiriciler kısıtı bir zincir boyunca iletir; ama zincirdeki her halka yine ebeveyn-çocuk ilişkisinin içindedir. Kardeşler arasında doğrudan bir kısıt yoktur. Bir öğenin konumunu başka bir kardeşe göre veren düzenlerde bu sınır görünür hâle gelir. Sonraki ders, kısıt tabanlı düzeni ölçer.
