Paylaşılan öğe geçişini özelleştir

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 hareketleri için kullanılan animasyon spesifikasyonunu değiştirmek istiyorsanız 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.

1. Şekil. Farklı boundsTransform parametrelerini
gösteren örnek

Yeniden 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 bakma (veya hedef) kısıtlamalarıyla ölçer. Ardından, çocuğun sabit düzeni, paylaşılan sınırlara sığacak şekilde ölçeklendirilir. ScaleToBounds, eyaletler arasında bir "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 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:

ScaleToBounds

RemeasureToBounds

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 durum, 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, yeniden akışın büyümesini engeller.

Modifier.skipToLookahead() yok. "Lorem Ipsum" metninin yeniden akıtıldığını fark edin.

Modifier.skipToLookahead() - "Lorem Ipsum" metninin, animasyonun başlangıcında son durumunu koruduğunu fark edin.

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 öğesine 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şturulmadığından emin olmanı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()'den gelen 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.

Modifier.renderInSharedTransitionScopeOverlay() olmadan

Modifier.renderInSharedTransitionScopeOverlay() ile

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, ortak öğ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
            }
        )
)

Şekil 2. Animasyon geçiş yaparken alt uygulama çubuğu kayarak girip çıkıyor.

Paylaşılan öğenizin bir yer paylaşımı içinde oluşturulmamasını istediğiniz nadir durumlarda renderInOverlayDuringTransition özelliğini sharedElement() olarak ayarlayabilirsiniz.

Kardeş düzenleri, paylaşılan öğe boyutundaki değişiklikler hakkında bilgilendirme

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.

PlaceholderSize.contentSize (varsayılan)

PlaceholderSize.animatedSize

(Listedeki diğer öğelerin, bir öğenin büyümesine yanıt olarak nasıl aşağıya doğru hareket ettiğine dikkat edin.)