Modifier — јесте непромјењиви објекат у Jetpack Compose-у који дефинише особине UI компоненте: величину, размаке, позадину, обраду гестова и понашање. Модификатори се обједињују у ланац кроз секвенцијални позив, при чему редослед њихове примјене критично утиче на резултат. Према Google Android Developers, 2026, правилна употреба Modifier-а је основа изградње флексибилног и продуктивног интерфејса у декларативном UI-ју.
Главне ствари
Modifier — је интерфејс из пакета androidx.compose.ui, који имплементира образац Composite. Сваки модификатор је елемент ланца који обавија претходни и додаје своје понашање. Modifier је непромјењив — сваке промјене стварају нови објекат копирањем са додавањем новог елемента у ланац. Ово омогућава безбједно дијељење једног Modifier-а између више компоненти.
Основне функције-модификатори се позивају кроз објекат-пратилац Modifier (нпр. Modifier.padding(), Modifier.fillMaxWidth()). Свака функција враћа нови Modifier са додатим елементом. Ако постоји више модификатора, они се обједињују у ланац: Modifier.padding(16.dp).fillMaxWidth().background(Color.Blue). Редослед је правац од споља ка унутра у односу на UI елемент.
За разлику од традиционалних View, гдје су се особине постављале кроз сеттере (view.setPadding(...), view.setBackground(...)), у Compose-у Modifier је декларативни опис. Компонента не „примјењује" модификаторе током рада — LayoutNode у фази композиције пролази кроз ланац Modifier-а и сакупља из њега листу Modifier.Element, које се затим обрађују у фази мјерења и распоређивања.
Редослед модификатора — једна од најчешћих грешака у Compose-у. Сваки модификатор обавија претходни, а операције се извршавају споља ка унутра. На примјер, padding(16.dp).clickable { }: прво се додаје размак око елемента, затим област клика укључује и размак. clickable { }.padding(16.dp): прво је област клика једнака величини елемента, затим се размак додаје около — клик на размак неће радити.
Правило памћења: читајте ланац с лијева на десно и примјењујте споља ка унутра. Први модификатор — најспољашњији, примјењује се на област око елемента. Посљедњи — најнутарњији, примјењује се директно на садржај. Модификатори величине (size, fillMaxWidth) треба да иду након размака, ако је размак потребан од родитеља, или прије размака, ако садржај прво треба ограничити, а затим центрирати.
Примјер: size(100.dp).padding(10.dp) — елемент фиксне величине 100dp, затим padding 10dp споља (коначна величина 120dp). padding(10.dp).size(100.dp) — padding 10dp смањује расположиви простор на (родитељ - 20dp), затим size(100dp) може препунити родитеља. Увијек промишљајте редослед свјесно, користећи тестове приказа за провјеру резултата.
| Редослед | Резултат |
|---|---|
| padding → clickable | Клик ради и на области размака |
| clickable → padding | Клик ради само на садржају, размак — мртва зона |
| size → padding | Елемент size(100), padding споља → 100+2*pad |
| padding → size | padding смањује мјесто, size може изаћи из граница |
| background → padding | Позадина испуњава цијели елемент укључујући спољашњу област |
| padding → background | Позадина само унутар размака (спољашња област провидна) |
Стандардна библиотека Compose-а укључује ~50+ модификатора, подијељених у категорије. Величина и позиционирање: Modifier.size(), width(), height(), fillMaxSize(), fillMaxWidth(), fillMaxHeight(), defaultMinSize(), requiredSize(). Размаци и границе: padding(), offset(), margin (смјешта се кроз padding родитеља или Layout). Декорација: background(), border(), clip(), alpha(), shadow(), blur().
Понашање и гестови: clickable(), combinedClickable(), pointerInput(), draggable(), swipeable(). Распоређивање у контејнеру: weight() (за Row/Column), align(), alignBy(), matchParentSize(). Семантика и приступачност: semantics(), testTag(), clearAndSetSemantics(). Цртање: drawBehind(), drawWithContent(), drawModifier() — модификатори који омогућавају прилагођено цртање на платну.
Семантички модификатори — посебна категорија. Modifier.semantics {} одређује како ће елемент бити представљен у Accessibility стаблу. Compose аутоматски попуњава семантику из текста, али за прилагођене компоненте треба ручно постављати улоге, стања и радње. Ово је критично за усклађеност са WCAG 2.2 и исправан рад TalkBack-а (Android) и VoiceOver-а (iOS).
@Composable
fun ModifierDemo() {
// Ланац модификатора са исправним редом
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("Додирни ме")
}
}
Modifier.composed — је фабрички метод који омогућава креирање сложених модификатора који могу користити друге модификаторе, LocalComposition и локално стање. За разлику од обичне функције проширења, composed креира инстанцу сваки пут при примјени, што омогућава да има сопствено стање унутар модификатора.
Када користити composed: понављајуће комбинације модификатора (нпр. стандардни стил картице: padding + background + border + clickable); модификатори са стањем (анимирана промјена позадине при притиску); приступ CompositionLocals-у (шема боја MaterialTheme, густина пиксела). У обичним случајевима довољна је обична функција проширења без composed-а.
Перформансе composed-а: сваки позив креира нови објекат модификатора, што може довести до додатних алокација при рекомпозицији. Да бисте то спријечили, умотајте composed у remember. Google препоручује коришћење composed-а само када је унутра заиста потребно стање или CompositionLocal. За статичке комбинације користите обичне функције проширења.
// Прилагођени модификатор кроз composed са стањем
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))
}
// Примјер употребе
@Composable
fun CardList() {
Column {
Box(Modifier.cardStyle()) { Text("Ставка 1") }
Box(Modifier.cardStyle(isSelected = true)) { Text("Изабрано") }
}
}
// Статичка верзија (без composed-а) — бржа
fun Modifier.simpleCardStyle(): Modifier =
this.fillMaxWidth().padding(8.dp).clip(RoundedCornerShape(4.dp))
Избјегавајте поновно креирање Modifier-а при свакој рекомпозицији. Ако модификатор не зависи од промјенљивих података — извуците га у константу или remember. Сваки пут када се позове Modifier.padding().background() стварају се нови објекти Modifier.Element. У изолованој компоненти то је непримјетно, али у LazyColumn-у са стотинама елемената додатне алокације изазивају примјетна заостајања при скроловању.
Правило: ако ланац модификатора не зависи од параметара Composable функције — декларишите га као val изван функције (на нивоу датотеке или Companion-а). Ако зависи — користите remember(зависност) { ... }. За модификаторе који су увијек исти, најефикаснији је val изван Composable-а: такви објекти се креирају једном током цијелог живота апликације.
Најбоље праксе редослиједа Modifier-а: распоредите модификаторе логичким редом: прво величина/размаци (layout), затим декорација (background, border), потом понашање (clickable, pointerInput). Ово не само да побољшава читљивост, већ помаже Compose Runtime-у да оптимизује ланац у фази мјерења. Такође избјегавајте претјерано угнијежђене Box-ове са различитим Modifier-има — често један Modifier на родитељском контејнеру може замијенити 2-3 угнијежђена.
// ✅ Добро: константа изван Composable-а
private val cardModifier = Modifier
.fillMaxWidth()
.padding(16.dp)
.clip(RoundedCornerShape(8.dp))
@Composable
fun CardContent() {
Box(cardModifier.background(Color.White)) { ... }
}
// ❌ Лоше: поновно креирање при свакој рекомпозицији
@Composable
fun BadCard() {
Box(Modifier.fillMaxWidth().padding(16.dp)) { ... }
}
// ✅ Добро: remember за динамички Modifier
@Composable
fun DynamicCard(color: Color) {
val modifier = remember(color) {
Modifier.fillMaxWidth().background(color)
}
Box(modifier) { ... }
}
Често постављана питања
Да, Modifier је непромјењив, па се један објекат може безбједно користити на више мјеста. Међутим, ако користите composed-модификатор, сваки позив креира нову инстанцу. За статичке ланце, константа или val изван Composable-а је оптимално рјешење.
Користите Layout Inspector у Android Studio-у — визуелно приказује границе сваког Modifier-а. За програмско отклањање грешака додајте Modifier.border() са различитим бојама на сваком кораку ланца да бисте видјели границе примјене сваког модификатора.
Modifier.then(other) прикључује ланац other на this. Секвенцијални позив (Modifier.a().b()) је еквивалентан Modifier.then(a()).then(b()). Нема разлике — то је исти механизам ланца. then() је користан када треба прикључити готов ланац из промјенљиве.
Modifier.semantics {} одређује како ће елемент бити описан за читач екрана. Modifier.clickable() аутоматски додаје улогу Button и Action(OnClick). За прилагођене гестове потребно је експлицитно навести semantics. Без семантичких модификатора, TalkBack корисници неће моћи да интерагују са прилагођеним компонентама.
Modifier.background(color, shape) ради са угловима, али clip() мора да иде ПРИЈЕ background-а да би углови били одсјечени. Исправан редослед: clip(shape).background(color). Ако треба одсјећи и садржај унутра, користите clipToBounds() на родитељу.
Резиме
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође