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

Paylaşılan öğe geçiş animasyonunun çalışma şeklini ö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 hareketi için kullanılan animasyon spesifikasyonunu değiştirmek üzere Modifier.sharedElement() üzerinde farklı bir boundsTransform parametresi belirtebilirsiniz. Bu, ilk Rect konumunu ve hedef Rect konumunu sağlar.

Örneğin, önceki örnekte bulunan metnin bir yay hareketiyle hareket etmesini sağlamak için boundsTransform parametresini belirterek keyframes spesifikasyonunu kullanın:

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.

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

Yeniden boyutlandırma modu

İki ortak 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 dönük (veya hedef) kısıtlamalarla ölçer. Daha sonra, alt yayıncının sabit düzeni, paylaşılan sınırlara sığacak şekilde ölçeklendirilir. ScaleToBounds, eyaletler arasındaki "grafik ölçek" olarak düşünülebilir.

RemeasureToBounds ise hedef boyuta göre sabit kısıtlamalarla sharedBounds alt düzenini yeniden ölçüp yeniden düzenler. Yeniden ölçüm, sınırların boyutu değiştiğinde tetiklenir. Bu durum her karede gerçekleşebilir.

Text bileşenleri için metnin farklı satırlara yeniden düzenlenmesini ve yeniden akışını önlediğinden ScaleToBounds önerilir. Farklı en boy oranına sahip sınırlar için ve paylaşılan iki öğe arasında sorunsuz bir devamlılık istiyorsanız RemeasureToBounds önerilir.

İki yeniden boyutlandırma modu arasındaki fark aşağıdaki örneklerde görülebilir:

ScaleToBounds

RemeasureToBounds

Son düzene atla

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 uygulanırken istenmeyen bir davranış olabilir.

Aşağıdaki örnekte, ekrana iki farklı şekilde giren "Lorem Ipsum" açıklama metni gösterilmektedir. İlk örnekte, kapsayıcı büyüdükçe metin girerken yeniden akışı sağlanır. İkinci örnekte ise metin büyüdükçe yeniden akışı sağlanmaz. Modifier.skipToLookaheadSize() eklemek, boyutu büyüdükçe yeniden akışı önler.

Modifier.skipToLookahead() yok - "Lorem Ipsum" metninin yeniden akışını fark edin

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

Klip ve yer paylaşımları

Oluşturma'da paylaşılan öğeler oluştururken dikkat edilmesi gereken önemli bir nokta, farklı kompozisyonlar arasında paylaşılabilmeleri için kompozisyonun oluşturulmasının, hedefteki eşleşmesine geçiş yapıldığında bir katman yer paylaşımına yükseltilmesidir. Bunun etkisi, üst öğenin sınırlarını ve katman dönüşümlerini (ör. alfa ve ölçek) atlamasıdır.

Paylaşılmayan diğer kullanıcı arayüzü öğelerinin üzerinde oluşturulur. Geçiş tamamlandığında öğe, yer paylaşımından kendi DrawScope alanına bırakılır.

Paylaşılan bir öğeyi bir şekle kırpmak için standart Modifier.clip() işlevini kullanın. Etiketi sharedElement() öğesinin 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 üst kapsayıcı dışında oluşturulmamasını sağlamanız gerekiyorsa clipInOverlayDuringTransition öğesini sharedElement() olarak ayarlayabilirsiniz. Varsayılan olarak, iç içe yerleştirilmiş paylaşılan sınırlar için clipInOverlayDuringTransition, sharedBounds() üst öğesindeki klip 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 üstte tutulmasını desteklemek için Modifier.renderInSharedTransitionScopeOverlay() özelliğini kullanın. Bu değiştirici, varsayılan olarak paylaşılan geçiş etkin olduğu sırada içeriği yer paylaşımında tutar.

Örneğin, Jetsnack'ta BottomAppBar öğesinin, ekran görünene kadar paylaşılan öğenin üzerine yerleştirilmesi gerekir. Değiştiriciyi bileşime eklemek, bileşimin yüksekte kalmasını sağlar.

Modifier.renderInSharedTransitionScopeOverlay() olmadan

Modifier.renderInSharedTransitionScopeOverlay() ile

Bazen paylaşılmayan composable'ınızın animasyonla birlikte geçişten önce diğer composable'ların üstünde kalmasını isteyebilirsiniz. Bu gibi durumlarda, paylaşılan öğe geçişi çalışırken bileşimi dışarı doğru animasyonlu olarak göstermek için renderInSharedTransitionScopeOverlay().animateEnterExit() öğesini kullanın:

JetsnackBottomBar(
    modifier = Modifier
        .renderInSharedTransitionScopeOverlay(
            zIndexInOverlay = 1f,
        )
        .animateEnterExit(
            enter = fadeIn() + slideInVertically {
                it
            },
            exit = fadeOut() + slideOutVertically {
                it
            }
        )
)

Şekil 2. Animasyon geçişleri sırasında alt uygulama çubuğunun kayması

Paylaşılan öğenizin yer paylaşımında oluşturulmamasını istediğiniz nadir durumlarda, sharedElement() üzerindeki renderInOverlayDuringTransition özelliğini false olarak ayarlayabilirsiniz.

Paylaşılan öğe boyutunda yapılan değişiklikleri kardeş düzenleri bildir

Varsayılan olarak sharedBounds() ve sharedElement(), düzen geçişleri sırasında üst kapsayıcıya boyut değişiklikleri hakkında bildirim göndermez.

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 bu değişikliğe yanıt verir.

PlaceholderSize.contentSize (varsayılan)

PlaceholderSize.animatedSize

(Listedeki diğer öğelerin, büyüyen öğeye yanıt olarak nasıl aşağı doğru hareket ettiğine dikkat edin)