Paylaşılan öğe geçiş animasyonunun nasıl çalışacağını özelleştirmek için paylaşılan öğelerin geçiş şeklini değiştirmek üzere kullanılabilecek birkaç parametre vardır.
Animasyon özellikleri
Boyut ve konum hareketinde kullanılan animasyon spesifikasyonunu değiştirmek için Modifier.sharedElement() üzerinde farklı bir boundsTransform parametresi belirtebilirsiniz.
Bu, ilk Rect konumunu ve hedef Rect konumunu sağlar.
Örneğin, önceki örnekteki metnin yay hareketiyle hareket etmesini sağlamak için keyframes spesifikasyonunu kullanmak üzere boundsTransform parametresini belirtin:
val textBoundsTransform = BoundsTransform { initialBounds, targetBounds -> keyframes { durationMillis = boundsAnimationDurationMillis initialBounds at 0 using ArcMode.ArcBelow using FastOutSlowInEasing targetBounds at boundsAnimationDurationMillis } } Text( "Cupcake", fontSize = 28.sp, modifier = Modifier.sharedBounds( rememberSharedContentState(key = "title"), animatedVisibilityScope = animatedVisibilityScope, boundsTransform = textBoundsTransform ) )
Herhangi bir AnimationSpec kullanabilirsiniz. Bu örnekte keyframes spesifikasyonu kullanılmaktadır.
boundsTransform parametreleriniYeniden boyutlandırma modu
İki paylaşılan sınır arasında animasyon yaparken resizeMode parametresini RemeasureToBounds veya ScaleToBounds olarak ayarlayabilirsiniz. Bu parametre, paylaşılan öğenin iki durum arasında nasıl geçiş yapacağını belirler. ScaleToBounds önce alt düzeni, ileriye bakma (veya hedef) kısıtlamalarıyla ölçer. Ardından, çocuğun sabit düzeni, paylaşılan sınırlar içine sığacak şekilde ölçeklendirilir.
ScaleToBounds, eyaletler arasındaki "grafik ölçek" olarak düşünülebilir.
Buna karşılık, RemeasureToBounds, hedef boyuta göre animasyonlu sabit kısıtlamalarla sharedBounds öğesinin alt düzenini yeniden ölçer ve yeniden düzenler. Yeniden ölçüm, sınır boyutu değişikliğiyle tetiklenir ve bu değişiklik her karede gerçekleşebilir.
Text composable'lar için ScaleToBounds önerilir. Bu sayede, metnin farklı satırlara yeniden yerleştirilmesi ve yeniden akıtılması önlenir. RemeasureToBounds, farklı en boy oranlarına sahip sınırlar için ve iki paylaşılan öğe arasında akıcı bir devamlılık istiyorsanız önerilir.
İki yeniden boyutlandırma modu arasındaki farkı aşağıdaki örneklerde görebilirsiniz:
|
|
|---|---|
Paylaşılan öğeleri dinamik olarak etkinleştirme ve devre dışı bırakma
Varsayılan olarak, hedef durumda eşleşen bir anahtar bulunduğunda düzen değişikliklerini canlandıracak şekilde sharedElement() ve sharedBounds() yapılandırılır. Ancak, gezinme yönü veya mevcut kullanıcı arayüzü durumu gibi belirli koşullara göre bu animasyonu dinamik olarak devre dışı bırakmak isteyebilirsiniz.
Paylaşılan öğe geçişinin gerçekleşip gerçekleşmeyeceğini kontrol etmek için SharedContentConfig öğesini rememberSharedContentState() öğesine ileterek özelleştirebilirsiniz. isEnabled özelliği, paylaşılan öğenin etkin olup olmadığını belirler.
Aşağıdaki örnekte, belirli ekranlar arasında gezinirken (ör. yalnızca A'dan B'ye) paylaşılan geçişi etkinleştiren, diğerleri için ise devre dışı bırakan bir yapılandırmanın nasıl tanımlanacağı gösterilmektedir.
SharedTransitionLayout { val transition = updateTransition(currentState) transition.AnimatedContent { targetState -> // Create the configuration that depends on state changing. fun animationConfig() : SharedTransitionScope.SharedContentConfig { return object : SharedTransitionScope.SharedContentConfig { override val SharedTransitionScope.SharedContentState.isEnabled: Boolean // For this example, we only enable the transition in one direction // from A -> B and not the other way around. get() = transition.currentState == "A" && transition.targetState == "B" } } when (targetState) { "A" -> Box( modifier = Modifier .sharedElement( rememberSharedContentState( key = "shared_box", config = animationConfig() ), animatedVisibilityScope = this ) // ... ) { // Your content } "B" -> { Box( modifier = Modifier .sharedElement( rememberSharedContentState( key = "shared_box", config = animationConfig() ), animatedVisibilityScope = this ) // ... ) { // Your content } } } } }
Varsayılan olarak, devam eden bir animasyon sırasında paylaşılan bir öğe devre dışı bırakılırsa, devam eden animasyon tamamlanır. Bu sayede, devam eden animasyonların yanlışlıkla kaldırılması önlenir. Animasyon devam ederken öğeyi kaldırmanız gerekiyorsa shouldKeepEnabledForOngoingAnimation arayüzünde SharedContentConfig'yi geçersiz kılarak false değerini döndürebilirsiniz.
Son düzene atlama
Varsayılan olarak, iki düzen arasında geçiş yapılırken düzen boyutu başlangıç ve son durumu arasında animasyonlu olarak değişir. Bu, metin gibi içeriklere animasyon eklerken istenmeyen bir davranış olabilir.
Aşağıdaki örnekte, "Lorem Ipsum" açıklama metninin ekrana iki farklı şekilde girdiği gösterilmektedir. İlk örnekte, metin kapsayıcı büyüdükçe yeniden düzenlenir. İkinci örnekte, metin büyüdükçe yeniden akmıyor. Modifier.skipToLookaheadSize() eklemek, büyüdükçe yeniden akışın gerçekleşmesini önler.
|
|
|---|---|
Klip ve yer paylaşımları
Paylaşılan öğelerin farklı composable'lar arasında paylaşılabilmesi için, geçiş hedefteki eşleşmesine başladığında composable'ın oluşturulması bir katman yer paylaşımına yükseltilir. Bu durumda, öğe üst öğenin sınırlarından ve katman dönüşümlerinden (ör. alfa ve ölçek) kaçar.
Paylaşılmayan diğer kullanıcı arayüzü öğelerinin üzerinde oluşturulur. Geçiş tamamlandıktan sonra öğe, yer paylaşımından kendi DrawScope'sine bırakılır.
Paylaşılan bir öğeyi şekle kırpmak için standart Modifier.clip()
işlevini kullanın. sharedElement() sonrasına yerleştirin:
Image( painter = painterResource(id = R.drawable.cupcake), contentDescription = "Cupcake", modifier = Modifier .size(100.dp) .sharedElement( rememberSharedContentState(key = "image"), animatedVisibilityScope = this@AnimatedContent ) .clip(RoundedCornerShape(16.dp)), contentScale = ContentScale.Crop )
Paylaşılan bir öğenin hiçbir zaman bir üst kapsayıcının dışında oluşturulmamasını sağlamanız gerekiyorsa sharedElement() üzerinde clipInOverlayDuringTransition değerini ayarlayabilirsiniz. Varsayılan olarak, iç içe yerleştirilmiş paylaşılan sınırlarda clipInOverlayDuringTransition, üst sharedBounds() öğesinden kırpma yolunu kullanır.
Paylaşılan öğe geçişi sırasında alt çubuk veya kayan işlem düğmesi gibi belirli kullanıcı arayüzü öğelerinin her zaman en üstte kalmasını sağlamak için Modifier.renderInSharedTransitionScopeOverlay() kullanın. Bu değiştirici, paylaşılan geçiş etkin olduğu süre boyunca içeriği yer paylaşımında tutar.
Örneğin, Jetsnack'te ekran görünür hale gelene kadar BottomAppBar, paylaşılan öğenin üzerine yerleştirilmelidir. Değiştiriciyi composable'a eklemek, composable'ı yükseltilmiş durumda tutar.
|
|
|---|---|
Geçişten önce, paylaşılmayan composable'ınızın animasyonla kaybolmasını ve diğer composable'ların üzerinde kalmasını isteyebilirsiniz. Bu gibi durumlarda, paylaşılan öğe geçişi çalışırken composable'ı animasyonla kapatmak için renderInSharedTransitionScopeOverlay().animateEnterExit() kullanın:
JetsnackBottomBar( modifier = Modifier .renderInSharedTransitionScopeOverlay( zIndexInOverlay = 1f, ) .animateEnterExit( enter = fadeIn() + slideInVertically { it }, exit = fadeOut() + slideOutVertically { it } ) )
Paylaşılan öğenizin bir yer paylaşımında oluşturulmasını istemediğiniz nadir durumlarda, renderInOverlayDuringTransition özelliğini sharedElement() üzerinde false olarak ayarlayabilirsiniz.
Paylaşılan öğe boyutundaki değişiklikleri kardeş düzenlere bildirme
Varsayılan olarak, sharedBounds() ve sharedElement(), düzen geçişleri sırasında üst kapsayıcıyı boyut değişiklikleri konusunda bilgilendirmez.
Boyut değişikliklerinin geçiş sırasında üst kapsayıcıya yayılması için placeHolderSize parametresini PlaceHolderSize.animatedSize olarak değiştirin. Bu işlem, öğenin büyümesine veya küçülmesine neden olur. Düzendeki diğer tüm öğeler değişikliğe yanıt verir.
|
(Listedeki diğer öğelerin, bir öğenin büyümesine karşılık olarak nasıl aşağıya doğru hareket ettiğine dikkat edin.) |
|---|---|