Modifier — řetězec modifikátorů a výkon v Compose

Autor: IT Sectr Publikováno: 2026-06-28 Doba čtení: 8 min

Modifier — je neměnný objekt v Jetpack Compose, který definuje vlastnosti UI komponenty: velikost, okraje, pozadí, zpracování gest a chování. Modifikátory se spojují do řetězce sekvenčním voláním, přičemž pořadí jejich aplikace kriticky ovlivňuje výsledek. Podle Google Android Developers, 2026 je správné použití Modifier základem budování flexibilního a výkonného rozhraní v deklarativním UI.

Hlavní body

  • Modifier — neměnný objekt popisující vzhled a chování UI komponenty
  • Řetězec modifikátorů se staví sekvenčně, pořadí ovlivňuje zobrazení
  • Pořadí má význam: padding → size se liší od size → padding
  • Modifier.composed umožňuje vytvářet vlastní složené modifikátory
  • Optimalizace: vyhněte se opětovnému vytváření Modifier při každé rekompozici

Co je Modifier v Jetpack Compose

Modifier — je rozhraní z balíčku androidx.compose.ui, které implementuje vzor Composite. Každý modifikátor je prvkem řetězce, který obaluje předchozí a přidává své vlastní chování. Modifier je neměnný — jakékoli změny vytvářejí nový objekt kopírováním s přidáním nového prvku do řetězce. To umožňuje bezpečné sdílení jednoho Modifier mezi více komponentami.

Základní funkce-modifikátory se volají přes průvodní objekt Modifier (např. Modifier.padding(), Modifier.fillMaxWidth()). Každá funkce vrací nový Modifier s přidaným prvkem. Pokud je modifikátorů více, spojí se do řetězce: Modifier.padding(16.dp).fillMaxWidth().background(Color.Blue). Pořadí je směr zvenčí dovnitř vzhledem k UI prvku.

Na rozdíl od tradičních View, kde se vlastnosti nastavovaly pomocí setterů (view.setPadding(...), view.setBackground(...)), v Compose je Modifier deklarativní popis. Komponenta modifikátory za běhu „neaplikuje" — LayoutNode ve fázi kompozice prochází řetězec Modifier a sbírá z něj seznam Modifier.Element, které se pak zpracovávají ve fázi měření a rozmístění.

Řetězec modifikátorů a pořadí aplikace

Pořadí modifikátorů — jedna z nejčastějších chyb v Compose. Každý modifikátor obaluje předchozí a operace se provádějí zvenčí dovnitř. Například padding(16.dp).clickable { }: nejprve se přidá okraj kolem prvku, poté oblast kliknutí zahrnuje i okraj. clickable { }.padding(16.dp): nejprve je oblast kliknutí rovna velikosti prvku, poté se okraj přidá kolem — kliknutí na okraj nebude fungovat.

Pravidlo pro zapamatování: čtěte řetězec zleva doprava a aplikujte zvenčí dovnitř. První modifikátor — nejvnější, aplikuje se na oblast kolem prvku. Poslední — nejvnitřnější, aplikuje se přímo na obsah. Modifikátory velikosti (size, fillMaxWidth) by měly následovat za okraji, pokud je okraj potřeba od rodiče, nebo před okraji, pokud má být obsah nejprve omezen a poté vycentrován.

Příklad: size(100.dp).padding(10.dp) — prvek pevné velikosti 100dp, poté padding 10dp zvenčí (konečná velikost 120dp). padding(10.dp).size(100.dp) — padding 10dp snižuje dostupný prostor na (rodič - 20dp), poté size(100dp) může rodiče přetéci. Vždy promýšlejte pořadí vědomě, pomocí testů zobrazení pro ověření výsledku.

PořadíVýsledek
padding → clickableKliknutí funguje i v oblasti okraje
clickable → paddingKliknutí funguje pouze na obsahu, okraj je mrtvá zóna
size → paddingPrvek size(100), padding zvenčí → 100+2*pad
padding → sizepadding snižuje místo, size může překročit hranice
background → paddingPozadí vyplňuje celý prvek včetně vnější oblasti
padding → backgroundPozadí pouze uvnitř okraje (vnější oblast průhledná)

Typy modifikátorů: velikost, okraje, dekorace a chování

Standardní knihovna Compose obsahuje ~50+ modifikátorů rozdělených do kategorií. Velikost a pozicování: Modifier.size(), width(), height(), fillMaxSize(), fillMaxWidth(), fillMaxHeight(), defaultMinSize(), requiredSize(). Okraje a hranice: padding(), offset(), margin (umístěno přes padding rodiče nebo Layout). Dekorace: background(), border(), clip(), alpha(), shadow(), blur().

Chování a gesta: clickable(), combinedClickable(), pointerInput(), draggable(), swipeable(). Umístění v kontejneru: weight() (pro Row/Column), align(), alignBy(), matchParentSize(). Sémantika a přístupnost: semantics(), testTag(), clearAndSetSemantics(). Kreslení: drawBehind(), drawWithContent(), drawModifier() — modifikátory umožňující vlastní kreslení na plátno.

Sémantické modifikátory — zvláštní kategorie. Modifier.semantics {} určuje, jak bude prvek reprezentován ve stromu Accessibility. Compose automaticky vyplňuje sémantiku z textu, ale pro vlastní komponenty je třeba ručně nastavit role, stavy a akce. To je kritické pro soulad s WCAG 2.2 a správnou funkci TalkBack (Android) a VoiceOver (iOS).

kotlin
@Composable
fun ModifierDemo() {
    // Řetězec modifikátorů se správným pořadím
    Box(
        modifier = Modifier
            .size(150.dp)
            .padding(8.dp)
            .border(2.dp, Color.Gray)
            .background(Color(0xFFE3F2FD))
            .clickable { /* handle click */ }
            .semantics {
                contentDescription = "Demo card with click action"
                role = Role.Button
            }
    ) {
        Text("Dotkni se mě")
    }
}

Vytváření vlastních modifikátorů pomocí Modifier.composed

Modifier.composed — je tovární metoda umožňující vytvářet složené modifikátory, které mohou používat jiné modifikátory, LocalComposition a lokální stav. Na rozdíl od běžné rozšiřující funkce, composed vytváří instanci pokaždé při aplikaci, což umožňuje mít vlastní stav uvnitř modifikátoru.

Kdy použít composed: opakující se kombinace modifikátorů (např. standardní styl karty: padding + background + border + clickable); modifikátory se stavem (animovaná změna pozadí při stisknutí); přístup k CompositionLocals (barevné schéma MaterialTheme, hustota pixelů). V běžných případech stačí obyčejná rozšiřující funkce bez composed.

Výkon composed: každé volání vytváří nový objekt modifikátoru, což může vést k nadbytečným alokacím při rekompozici. Abyste tomu předešli, obalte composed do remember. Google doporučuje používat composed pouze tehdy, když je uvnitř skutečně potřeba stav nebo CompositionLocal. Pro statické kombinace používejte běžné rozšiřující funkce.

kotlin
// Vlastní modifikátor přes composed se stavem
fun Modifier.cardStyle(
    elevation: Dp = 4.dp,
    isSelected: Boolean = false
): Modifier = this.composed {
    val backgroundColor = if (isSelected)
        MaterialTheme.colorScheme.primaryContainer
    else
        MaterialTheme.colorScheme.surface

    this
        .fillMaxWidth()
        .padding(12.dp)
        .background(backgroundColor, RoundedCornerShape(8.dp))
        .shadow(elevation, RoundedCornerShape(8.dp))
}

// Příklad použití
@Composable
fun CardList() {
    Column {
        Box(Modifier.cardStyle()) { Text("Položka 1") }
        Box(Modifier.cardStyle(isSelected = true)) { Text("Vybráno") }
    }
}

// Statická verze (bez composed) — rychlejší
fun Modifier.simpleCardStyle(): Modifier =
    this.fillMaxWidth().padding(8.dp).clip(RoundedCornerShape(4.dp))

Výkon Modifier a nejlepší postupy

Vyhněte se opětovnému vytváření Modifier při každé rekompozici. Pokud modifikátor nezávisí na proměnných datech — vyjměte ho do konstanty nebo remember. Při každém volání Modifier.padding().background() se vytvářejí nové objekty Modifier.Element. V izolované komponentě je to nepostřehnutelné, ale v LazyColumn se stovkami prvků způsobují nadbytečné alokace znatelné zpoždění při scrollování.

Pravidlo: pokud řetězec modifikátorů nezávisí na parametrech Composable funkce — deklarujte jej jako val mimo funkci (na úrovni souboru nebo Companion). Pokud závisí — použijte remember(závislost) { ... }. Pro modifikátory, které jsou vždy stejné, je nejefektivnější val mimo Composable: takové objekty se vytvoří jednou za celou dobu životnosti aplikace.

Nejlepší postupy řazení Modifier: umístěte modifikátory v logickém pořadí: nejprve velikost/okraje (layout), pak dekorace (background, border), poté chování (clickable, pointerInput). To nejen zlepšuje čitelnost, ale také pomáhá Compose Runtime optimalizovat řetězec ve fázi měření. Také se vyhněte nadměrnému vnořování Boxů s různými Modifier — často jeden Modifier na nadřazeném kontejneru může nahradit 2-3 vnořené.

kotlin
// ✅ Dobře: konstanta mimo Composable
private val cardModifier = Modifier
    .fillMaxWidth()
    .padding(16.dp)
    .clip(RoundedCornerShape(8.dp))

@Composable
fun CardContent() {
    Box(cardModifier.background(Color.White)) { ... }
}

// ❌ Špatně: opětovné vytváření při každé rekompozici
@Composable
fun BadCard() {
    Box(Modifier.fillMaxWidth().padding(16.dp)) { ... }
}

// ✅ Dobře: remember pro dynamický Modifier
@Composable
fun DynamicCard(color: Color) {
    val modifier = remember(color) {
        Modifier.fillMaxWidth().background(color)
    }
    Box(modifier) { ... }
}

Často kladené otázky

Lze použít jeden Modifier pro více Composable?

Ano, Modifier je neměnný, takže jeden objekt lze bezpečně použít na více místech. Pokud však používáte composed modifikátor, každé volání vytváří novou instanci. Pro statické řetězce je konstanta nebo val mimo Composable optimálním řešením.

Jak ladit řetězec modifikátorů?

Použijte Layout Inspector v Android Studio — vizuálně zobrazuje hranice každého Modifier. Pro programové ladění přidejte Modifier.border() s různými barvami v každém kroku řetězce, abyste viděli hranice aplikace každého modifikátoru.

Co je Modifier.then() a čím se liší od sekvenčního volání?

Modifier.then(other) připojuje řetězec other k this. Sekvenční volání (Modifier.a().b()) je ekvivalentní Modifier.then(a()).then(b()). Není v tom rozdíl — je to stejný mechanismus řetězení. then() je užitečný, když potřebujete připojit hotový řetězec z proměnné.

Jak Modifier ovlivňuje sémantiku Accessibility?

Modifier.semantics {} určuje, jak bude prvek popsán pro čtečku obrazovky. Modifier.clickable() automaticky přidává roli Button a Action(OnClick). Pro vlastní gesta je třeba explicitně specifikovat semantics. Bez sémantických modifikátorů nebudou uživatelé TalkBack schopni interagovat s vlastními komponentami.

Proč background v Modifier nefunguje se zaoblenými rohy?

Modifier.background(color, shape) funguje s rohy, ale clip() musí být PŘED background, aby se rohy ořízly. Správné pořadí: clip(shape).background(color). Pokud potřebujete oříznout i obsah uvnitř, použijte clipToBounds() na rodiči.

Shrnutí

  • Modifier — neměnný objekt pro deklarativní popis vzhledu a chování
  • Pořadí modifikátorů určuje výsledek: padding → clickable vs clickable → padding
  • Řetězec se staví sekvenčně, každý prvek obaluje předchozí
  • Modifier.composed umožňuje vytvářet modifikátory se stavem a CompositionLocal
  • Výkon: vyjímejte statické řetězce do konstant, použijte remember pro dynamické
  • Sémantika: Modifier.semantics je povinný pro Accessibility vlastních komponent
  • Doporučení: řaďte modifikátory od layoutu k dekoraci, poté k chování

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také