Paylaşılan öğe geçiş animasyonunun nasıl çalışacağını özelleştirmek için paylaşılan öğelerin geçiş şeklini değiştirmek amacıyla kullanılabilecek birkaç parametre vardır.
Animasyon özellikleri
Boyut ve konum hareketi için kullanılan animasyon spesifikasyonunu değiştirmek isterseniz 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 kullanacak 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 ) )
İstediğiniz AnimationSpec kullanabilirsiniz. Bu örnekte keyframes spesifikasyonu kullanılmıştır.
boundsTransform parametreleriniYeniden boyutlandırma modu
İki paylaşılan sınır arasında animasyon oluştururken 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 yönelik (veya hedef) kısıtlamalarla ölçer. Ardından, alt öğenin sabit düzeni, paylaşılan sınırlara sığacak şekilde ölçeklendirilir.
ScaleToBounds, eyaletler arasında bir "grafik ölçeği" 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. Bu değişiklik her karede gerçekleşebilir.
Text bileşenleri için ScaleToBounds kullanılması önerilir. Bu sayede, metnin farklı satırlara yeniden yerleştirilmesi ve yeniden akması önlenir. RemeasureToBounds, farklı en-boy oranlarına sahip sınırlar için ve iki paylaşılan öğe arasında akıcı bir süreklilik 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 sharedElement() ve sharedBounds(), hedef durumda eşleşen bir anahtar bulunduğunda düzen değişikliklerini animasyonlu hale getirecek şekilde 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 rememberSharedContentState() öğesine iletilen SharedContentConfig değerini özelleştirebilirsiniz. isEnabled özelliği, paylaşılan öğenin etkin olup olmadığını belirler.
Aşağıdaki örnekte, paylaşılan geçişi yalnızca belirli ekranlar arasında gezinirken (ör. yalnızca A'dan B'ye) etkinleştiren, diğer ekranlar için 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 animasyonların yanlışlıkla kaldırılmasını önlemek için mevcut animasyon tamamlanır. Animasyon devam ederken öğeyi kaldırmanız gerekiyorsa SharedContentConfig arayüzünde shouldKeepEnabledForOngoingAnimation yöntemini geçersiz kılarak false döndürmesini sağlayabilirsiniz.
Son düzene atla
Varsayılan olarak, iki düzen arasında geçiş yaparken düzen boyutu, başlangıç ve son durumu arasında animasyonlu olarak değişir. Metin gibi içeriklere animasyon eklerken bu durum istenmeyen bir davranış olabilir.
Aşağıdaki örnekte, "Lorem Ipsum" açıklama metninin ekrana iki farklı şekilde girdiği gösterilmektedir. İlk örnekte, kapsayıcı büyüdükçe metin
girerken yeniden düzenlenir. İkinci örnekte ise metin büyüdükçe yeniden akmıyor. Modifier.skipToLookaheadSize() eklemek, büyüdükçe yeniden akışı engeller.
Hayır |
|
|---|---|
Klip ve yer paylaşımları
Paylaşılan öğelerin farklı composable'lar arasında paylaşılması için, hedefteki eşleşmesine geçiş başlatıldığında composable'ın oluşturulması bir katman yer paylaşımına yükseltilir. Bu sayede, ü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ığında öğe, yer paylaşımlı reklamdan kendi DrawScope öğesine bırakılır.
Paylaşılan bir öğeyi bir şekle kırpmak için standart Modifier.clip() işlevini kullanın. sharedElement() ifadesinden sonra 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 ü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ırlar için clipInOverlayDuringTransition, üst öğe sharedBounds()'ten gelen kırpma yolunu kullanır.
Alt çubuk veya kayan işlem düğmesi gibi belirli kullanıcı arayüzü öğelerini paylaşılan öğe geçişi sırasında her zaman en üstte tutmak için Modifier.renderInSharedTransitionScopeOverlay() kullanın. Varsayılan olarak bu değiştirici, paylaşılan geçiş etkin olduğu sürece içeriği yer paylaşımında tutar.
Örneğin, Jetsnack'te BottomAppBar, ekran görünmez olana kadar paylaşılan öğenin üzerine yerleştirilmelidir. Değiştiriciyi composable'a eklediğinizde composable yükseltilmiş olarak kalır.
|
|
|---|---|
Paylaşılmayan composable'ınızın animasyonlu bir şekilde kaybolmasını ve geçişten önce diğer composable'ların üzerinde kalmasını isteyebilirsiniz. Bu gibi durumlarda, paylaşılan öğe geçişi çalışırken composable'ın animasyonunu kaldırmak 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, sharedElement() üzerindeki renderInOverlayDuringTransition değerini false olarak ayarlayabilirsiniz.
Paylaşılan öğe boyutundaki değişiklikleri eş düzey düzenlere bildirme
Varsayılan olarak sharedBounds() ve sharedElement(), düzen geçişleri sırasında boyut değişikliklerini üst kapsayıcıya bildirmez.
Boyut değişikliklerini geçiş sırasında üst kapsayıcıya yaymak için placeholderSize parametresini PlaceholderSize.AnimatedSize olarak değiştirin. Bunu yaptığınızda öğe büyür veya küçülür. Düzendeki diğer tüm öğeler bu değişikliğe yanıt verir.
|
(Listedeki diğer öğelerin, büyüyen öğeye göre nasıl aşağı kaydığına dikkat edin.) |
|---|---|