Compose'da birçok yerleşik animasyon mekanizması vardır ve hangisini seçeceğinizi bilmek zor olabilir. Yaygın animasyon kullanım alanlarının listesini aşağıda bulabilirsiniz. Kullanabileceğiniz farklı API seçeneklerinin tamamı hakkında daha ayrıntılı bilgi için Compose Animation dokümanının tamamını okuyun.
Sık kullanılan composable özelliklerini canlandırma
Compose, birçok yaygın animasyon kullanım alanını çözmenize olanak tanıyan kullanışlı API'ler sunar. Bu bölümde, bir composable'ın ortak özelliklerini nasıl canlandırabileceğiniz gösterilmektedir.
Görünme / kaybolma animasyonu

Bir Composable'ı gizlemek veya göstermek için AnimatedVisibility
öğesini kullanın. AnimatedVisibility
içindeki çocuklar kendi giriş veya çıkış geçişleri için Modifier.animateEnterExit()
öğesini kullanabilir.
var visible by remember { mutableStateOf(true) } // Animated visibility will eventually remove the item from the composition once the animation has finished. AnimatedVisibility(visible) { // your composable here // ... }
AnimatedVisibility
öğesinin giriş ve çıkış parametreleri, composable'ın göründüğünde ve kaybolduğunda nasıl davranacağını yapılandırmanıza olanak tanır. Daha fazla bilgi için tam dokümanı okuyun.
Bir composable'ın görünürlüğünü canlandırmanın bir başka yolu da animateFloatAsState
kullanarak alfa değerini zaman içinde canlandırmaktır:
var visible by remember { mutableStateOf(true) } val animatedAlpha by animateFloatAsState( targetValue = if (visible) 1.0f else 0f, label = "alpha" ) Box( modifier = Modifier .size(200.dp) .graphicsLayer { alpha = animatedAlpha } .clip(RoundedCornerShape(8.dp)) .background(colorGreen) .align(Alignment.TopCenter) ) { }
Ancak alfa değerini değiştirirken, composable'ın kompozisyonda kalmaya
devam edeceği ve yerleştirildiği alanı kaplamayı sürdüreceği unutulmamalıdır. Bu durum, ekran okuyucuların ve diğer erişilebilirlik mekanizmalarının ekrandaki öğeyi dikkate almaya devam etmesine neden olabilir. Diğer yandan, AnimatedVisibility
öğeyi kompozisyondan kalıcı olarak kaldırır.

Arka plan rengini animasyonla değiştirme

val animatedColor by animateColorAsState( if (animateBackgroundColor) colorGreen else colorBlue, label = "color" ) Column( modifier = Modifier.drawBehind { drawRect(animatedColor) } ) { // your composable here }
Bu seçenek, Modifier.background()
kullanmaktan daha iyi performans gösterir.
Modifier.background()
, tek seferlik renk ayarı için kabul edilebilir ancak zaman içinde bir renge animasyon uygularken gerekenden daha fazla yeniden oluşturmaya neden olabilir.
Arka plan rengini sonsuza kadar canlandırmak için animasyonu tekrarlama bölümüne bakın.
Bir composable'ın boyutunu canlandırma

Compose, composable'ların boyutunu birkaç farklı şekilde canlandırmanıza olanak tanır. Birleştirilebilir boyut değişiklikleri arasındaki animasyonlar için animateContentSize()
kullanın.
Örneğin, bir satırdan birden fazla satıra genişleyebilen metin içeren bir kutunuz varsa daha sorunsuz bir geçiş için Modifier.animateContentSize()
kullanabilirsiniz:
var expanded by remember { mutableStateOf(false) } Box( modifier = Modifier .background(colorBlue) .animateContentSize() .height(if (expanded) 400.dp else 200.dp) .fillMaxWidth() .clickable( interactionSource = remember { MutableInteractionSource() }, indication = null ) { expanded = !expanded } ) { }
Boyut değişikliklerinin nasıl yapılması gerektiğini açıklamak için SizeTransform
ile birlikte AnimatedContent
de kullanabilirsiniz.
Composable'ın konumuna animasyon uygulama

Bir composable'ın konumunu canlandırmak için Modifier.offset{ }
ile animateIntOffsetAsState()
'ı birlikte kullanın.
var moved by remember { mutableStateOf(false) } val pxToMove = with(LocalDensity.current) { 100.dp.toPx().roundToInt() } val offset by animateIntOffsetAsState( targetValue = if (moved) { IntOffset(pxToMove, pxToMove) } else { IntOffset.Zero }, label = "offset" ) Box( modifier = Modifier .offset { offset } .background(colorBlue) .size(100.dp) .clickable( interactionSource = remember { MutableInteractionSource() }, indication = null ) { moved = !moved } )
Konum veya boyut animasyonu yaparken composable'ların diğer composable'ların üzerinde ya da altında çizilmemesini sağlamak istiyorsanız Modifier.layout{ }
kullanın. Bu değiştirici, boyut ve konum değişikliklerini üst öğeye yayar. Bu değişiklikler de diğer alt öğeleri etkiler.
Örneğin, bir Box
öğesini Column
içinde taşıyorsanız ve Box
taşındığında diğer alt öğelerin de taşınması gerekiyorsa Modifier.layout{ }
ile birlikte şu şekilde dengeleme bilgilerini ekleyin:
var toggled by remember { mutableStateOf(false) } val interactionSource = remember { MutableInteractionSource() } Column( modifier = Modifier .padding(16.dp) .fillMaxSize() .clickable(indication = null, interactionSource = interactionSource) { toggled = !toggled } ) { val offsetTarget = if (toggled) { IntOffset(150, 150) } else { IntOffset.Zero } val offset = animateIntOffsetAsState( targetValue = offsetTarget, label = "offset" ) Box( modifier = Modifier .size(100.dp) .background(colorBlue) ) Box( modifier = Modifier .layout { measurable, constraints -> val offsetValue = if (isLookingAhead) offsetTarget else offset.value val placeable = measurable.measure(constraints) layout(placeable.width + offsetValue.x, placeable.height + offsetValue.y) { placeable.placeRelative(offsetValue) } } .size(100.dp) .background(colorGreen) ) Box( modifier = Modifier .size(100.dp) .background(colorBlue) ) }

Modifier.layout{ }
Bir composable'ın dolgusunu canlandırma

Bir composable'ın dolgusunu animasyonla göstermek için animateDpAsState
ile Modifier.padding()
'ı birlikte kullanın:
var toggled by remember { mutableStateOf(false) } val animatedPadding by animateDpAsState( if (toggled) { 0.dp } else { 20.dp }, label = "padding" ) Box( modifier = Modifier .aspectRatio(1f) .fillMaxSize() .padding(animatedPadding) .background(Color(0xff53D9A1)) .clickable( interactionSource = remember { MutableInteractionSource() }, indication = null ) { toggled = !toggled } )
Bir composable'ın yüksekliğine animasyon uygulama
Bir composable'ın yüksekliğini canlandırmak için animateDpAsState
ile Modifier.graphicsLayer{ }
'ı birlikte kullanın. Tek seferlik yükseklik değişiklikleri için Modifier.shadow()
simgesini kullanın. Gölgeyi animasyonlandırıyorsanız Modifier.graphicsLayer{ }
değiştiricisini kullanmak daha iyi performans sağlar.
val mutableInteractionSource = remember { MutableInteractionSource() } val pressed = mutableInteractionSource.collectIsPressedAsState() val elevation = animateDpAsState( targetValue = if (pressed.value) { 32.dp } else { 8.dp }, label = "elevation" ) Box( modifier = Modifier .size(100.dp) .align(Alignment.Center) .graphicsLayer { this.shadowElevation = elevation.value.toPx() } .clickable(interactionSource = mutableInteractionSource, indication = null) { } .background(colorGreen) ) { }
Alternatif olarak, Card
composable'ı kullanın ve yükseklik özelliğini duruma göre farklı değerlere ayarlayın.
Metin ölçeğine, çeviriye veya döndürmeye animasyon ekleme

Metnin ölçeğini, çevirisini veya dönüşünü canlandırırken textMotion
parametresini TextStyle
üzerinde TextMotion.Animated
olarak ayarlayın. Bu sayede metin animasyonları arasında daha sorunsuz geçişler sağlanır. Metni çevirmek, döndürmek veya ölçeklendirmek için Modifier.graphicsLayer{ }
simgesini kullanın.
val infiniteTransition = rememberInfiniteTransition(label = "infinite transition") val scale by infiniteTransition.animateFloat( initialValue = 1f, targetValue = 8f, animationSpec = infiniteRepeatable(tween(1000), RepeatMode.Reverse), label = "scale" ) Box(modifier = Modifier.fillMaxSize()) { Text( text = "Hello", modifier = Modifier .graphicsLayer { scaleX = scale scaleY = scale transformOrigin = TransformOrigin.Center } .align(Alignment.Center), // Text composable does not take TextMotion as a parameter. // Provide it via style argument but make sure that we are copying from current theme style = LocalTextStyle.current.copy(textMotion = TextMotion.Animated) ) }
Metin rengine animasyon ekleme

Metin rengini canlandırmak için BasicText
composable'da color
lambda'yı kullanın:
val infiniteTransition = rememberInfiniteTransition(label = "infinite transition") val animatedColor by infiniteTransition.animateColor( initialValue = Color(0xFF60DDAD), targetValue = Color(0xFF4285F4), animationSpec = infiniteRepeatable(tween(1000), RepeatMode.Reverse), label = "color" ) BasicText( text = "Hello Compose", color = { animatedColor }, // ... )
Farklı içerik türleri arasında geçiş yapma

Farklı composable'lar arasında animasyon oluşturmak için AnimatedContent
kullanın. Composables arasında yalnızca standart bir geçiş istiyorsanız Crossfade
kullanın.
var state by remember { mutableStateOf(UiState.Loading) } AnimatedContent( state, transitionSpec = { fadeIn( animationSpec = tween(3000) ) togetherWith fadeOut(animationSpec = tween(3000)) }, modifier = Modifier.clickable( interactionSource = remember { MutableInteractionSource() }, indication = null ) { state = when (state) { UiState.Loading -> UiState.Loaded UiState.Loaded -> UiState.Error UiState.Error -> UiState.Loading } }, label = "Animated Content" ) { targetState -> when (targetState) { UiState.Loading -> { LoadingScreen() } UiState.Loaded -> { LoadedScreen() } UiState.Error -> { ErrorScreen() } } }
AnimatedContent
, birçok farklı giriş ve çıkış geçişi gösterecek şekilde özelleştirilebilir. Daha fazla bilgi için AnimatedContent
ile ilgili dokümanları veya AnimatedContent
ile ilgili blog yayınını okuyun.
Farklı hedeflere giderken animasyon oynatma

navigation-compose yapay nesnesi kullanılırken composable'lar arasındaki geçişleri canlandırmak için composable'da enterTransition
ve exitTransition
özelliklerini belirtin. Ayrıca, üst düzeydeki tüm hedefler için kullanılacak varsayılan animasyonu da ayarlayabilirsiniz NavHost
:
val navController = rememberNavController() NavHost( navController = navController, startDestination = "landing", enterTransition = { EnterTransition.None }, exitTransition = { ExitTransition.None } ) { composable("landing") { ScreenLanding( // ... ) } composable( "detail/{photoUrl}", arguments = listOf(navArgument("photoUrl") { type = NavType.StringType }), enterTransition = { fadeIn( animationSpec = tween( 300, easing = LinearEasing ) ) + slideIntoContainer( animationSpec = tween(300, easing = EaseIn), towards = AnimatedContentTransitionScope.SlideDirection.Start ) }, exitTransition = { fadeOut( animationSpec = tween( 300, easing = LinearEasing ) ) + slideOutOfContainer( animationSpec = tween(300, easing = EaseOut), towards = AnimatedContentTransitionScope.SlideDirection.End ) } ) { backStackEntry -> ScreenDetails( // ... ) } }
Gelen ve giden içeriğe farklı efektler uygulayan birçok farklı giriş ve çıkış geçişi türü vardır. Daha fazla bilgi için belgelere bakın.
2.7.0-alpha01 sürümünde kullanılabilir.Animasyonu tekrar oynatma

Animasyonunuzun sürekli olarak tekrar etmesi için infiniteRepeatable
animationSpec
ile birlikte rememberInfiniteTransition
kullanın. Nasıl ileri geri gideceğini belirtmek için RepeatModes
simgesini değiştirin.
Belirli sayıda tekrarlamak için finiteRepeatable
kullanın.
val infiniteTransition = rememberInfiniteTransition(label = "infinite") val color by infiniteTransition.animateColor( initialValue = Color.Green, targetValue = Color.Blue, animationSpec = infiniteRepeatable( animation = tween(1000, easing = LinearEasing), repeatMode = RepeatMode.Reverse ), label = "color" ) Column( modifier = Modifier.drawBehind { drawRect(color) } ) { // your composable here }
Bir composable başlatıldığında animasyon başlatma
LaunchedEffect
, bir composable kompozisyona girdiğinde çalışır. Bir composable başlatıldığında animasyon başlatır. Bunu, animasyon durum değişikliğini yönlendirmek için kullanabilirsiniz. Lansmanda animasyonu başlatmak için Animatable
ile animateTo
yöntemini kullanma:
val alphaAnimation = remember { Animatable(0f) } LaunchedEffect(Unit) { alphaAnimation.animateTo(1f) } Box( modifier = Modifier.graphicsLayer { alpha = alphaAnimation.value } )
Sıralı animasyonlar oluşturma

Sıralı veya eşzamanlı animasyonlar gerçekleştirmek için Animatable
coroutine API'lerini kullanın. Animatable
üzerinde animateTo
işlevini art arda çağırmak, her animasyonun devam etmeden önce önceki animasyonların tamamlanmasını beklemesine neden olur .
Bunun nedeni, bu işlevin askıya alma işlevi olmasıdır.
val alphaAnimation = remember { Animatable(0f) } val yAnimation = remember { Animatable(0f) } LaunchedEffect("animationKey") { alphaAnimation.animateTo(1f) yAnimation.animateTo(100f) yAnimation.animateTo(500f, animationSpec = tween(100)) }
Eş zamanlı animasyonlar oluşturma

Eşzamanlı animasyonlar elde etmek için coroutine API'lerini (Animatable#animateTo()
veya animate
) ya da Transition
API'yi kullanın. Bir coroutine bağlamında birden fazla başlatma işlevi kullanırsanız animasyonlar aynı anda başlatılır:
val alphaAnimation = remember { Animatable(0f) } val yAnimation = remember { Animatable(0f) } LaunchedEffect("animationKey") { launch { alphaAnimation.animateTo(1f) } launch { yAnimation.animateTo(100f) } }
Aynı durumu aynı anda birçok farklı özellik animasyonunu yönlendirmek için kullanmak üzere updateTransition
API'yi kullanabilirsiniz. Aşağıdaki örnekte, durum değişikliğiyle kontrol edilen iki özellik (rect
ve borderWidth
) animasyonla gösterilmektedir:
var currentState by remember { mutableStateOf(BoxState.Collapsed) } val transition = updateTransition(currentState, label = "transition") val rect by transition.animateRect(label = "rect") { state -> when (state) { BoxState.Collapsed -> Rect(0f, 0f, 100f, 100f) BoxState.Expanded -> Rect(100f, 100f, 300f, 300f) } } val borderWidth by transition.animateDp(label = "borderWidth") { state -> when (state) { BoxState.Collapsed -> 1.dp BoxState.Expanded -> 0.dp } }
Animasyon performansını optimize etme
Oluşturma bölümündeki animasyonlar performans sorunlarına neden olabilir. Bunun nedeni, animasyonun doğasıdır: Hareket yanılsaması oluşturmak için ekrandaki piksellerin kare kare hareket etmesi veya hızlıca değişmesi.
Compose'un farklı aşamalarını (oluşturma, düzen ve çizim) göz önünde bulundurun. Animasyonunuz düzen aşamasını değiştirirse etkilenen tüm composable'ların yeniden düzenlenmesi ve yeniden çizilmesi gerekir. Animasyonunuz çizim aşamasında gerçekleşirse genel olarak daha az iş yapması gerektiğinden animasyonu düzen aşamasında çalıştırmanıza kıyasla varsayılan olarak daha iyi performans gösterir.
Uygulamanızın animasyon sırasında mümkün olduğunca az işlem yapmasını sağlamak için mümkün olduğunda Modifier
lambda sürümünü seçin. Bu, yeniden oluşturmayı atlar ve animasyonu oluşturma aşamasının dışında gerçekleştirir. Aksi takdirde, bu değiştirici her zaman çizim aşamasında çalıştığından Modifier.graphicsLayer{ }
kullanın. Bu konu hakkında daha fazla bilgi için performans belgelerindeki okuma işlemlerini erteleme bölümüne bakın.
Animasyon zamanlamasını değiştirme
Compose, çoğu animasyon için varsayılan olarak spring animasyonlarını kullanır. Yaylar veya fizik tabanlı animasyonlar daha doğal görünür. Ayrıca, sabit bir süre yerine nesnenin mevcut hızını dikkate aldıkları için kesintiye uğratılabilirler.
Varsayılanı geçersiz kılmak istiyorsanız yukarıda gösterilen tüm animasyon API'leri, animasyonun nasıl çalışacağını özelleştirmek için bir animationSpec
ayarlama olanağına sahiptir. Örneğin, animasyonun belirli bir süre boyunca yürütülmesini veya daha fazla sıçramasını sağlayabilirsiniz.
Farklı animationSpec
seçeneklerinin özeti aşağıda verilmiştir:
spring
: Tüm animasyonlar için varsayılan olan fizik tabanlı animasyon. Farklı bir animasyon görünümü ve hissi elde etmek için sertliği veya dampingRatio'yu değiştirebilirsiniz.tween
(between kelimesinin kısaltması): Süreye dayalı animasyon,Easing
işleviyle iki değer arasında animasyon oluşturur.keyframes
: Animasyondaki belirli önemli noktalarda değerleri belirtme spesifikasyonu.repeatable
:RepeatMode
ile belirtilen belirli sayıda çalışan süreye dayalı spesifikasyon.infiniteRepeatable
: Süreye dayalı ve süresiz olarak çalışan bir spesifikasyon.snap
: Animasyon olmadan anında son değere geçer.

animationSpecs hakkında daha fazla bilgi için belgenin tamamını okuyun.
Ek kaynaklar
Compose'daki eğlenceli animasyonlarla ilgili daha fazla örnek için aşağıdakilere göz atın:
- Oluşturma'da 5 hızlı animasyon
- Oluşturma'da Jellyfish'i hareket ettirme
- Oluşturma penceresinde
AnimatedContent
simgesini özelleştirme - Compose'da Easing işlevlerine giriş