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 — 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í.
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 → clickable | Kliknutí funguje i v oblasti okraje |
| clickable → padding | Kliknutí funguje pouze na obsahu, okraj je mrtvá zóna |
| size → padding | Prvek size(100), padding zvenčí → 100+2*pad |
| padding → size | padding snižuje místo, size může překročit hranice |
| background → padding | Pozadí vyplňuje celý prvek včetně vnější oblasti |
| padding → background | Pozadí pouze uvnitř okraje (vnější oblast průhledná) |
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).
@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ě")
}
}
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.
// 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))
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é.
// ✅ 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
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.
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.
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é.
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.
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í
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í.
Přečtěte si také