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 için kullanılabilecek birkaç parametre vardır.

Animasyon özellikleri

Boyut ve konum hareketi için kullanılan animasyon özelliklerini değiştirmek üzere Modifier.sharedElement() öğesinde farklı bir boundsTransform parametresi belirtebilirsiniz. Bu, başlangıç Rect konumunu ve hedef Rect konumunu sağlar.

Örneğin, önceki örnekte yer alan metnin bir yay hareketiyle hareket etmesini sağlamak için bir keyframes spesifikasyonu 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.

Şekil 1. 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, öncelikle alt düzeni ileri dönük (veya hedef) kısıtlamalarıyla ölçer. Ardından alt öğenin kararlı düzeni, paylaşılan sınırlara sığacak şekilde ölçeklendirilir. ScaleToBounds, eyaletler arasındaki "grafiksel ölçek" olarak düşünülebilir.

RemeasureToBounds ise sharedBounds alt düzenini, hedef boyuta göre animasyonlu sabit kısıtlamalarla yeniden ölçüp düzenler. Yeniden ölçüm, sınırların boyutu değişikliği ile tetiklenir. Bu, potansiyel olarak her kare olabilir.

Metnin farklı satırlara yönlendirilmesini ve yeniden düzenlenmesini önleyeceği için Text composable'lar için ScaleToBounds önerilir. Farklı en boy oranlarına sahip sınırlar için ve paylaşılan iki öğe arasında değişken süreklilik 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 animasyon oluşturur. Bu, metin gibi içerikleri canlandırırken istenmeyen bir davranış olabilir.

Aşağıdaki örnekte ekrana iki farklı şekilde giren "Lorem Ipsum" açıklama metni gösterilmektedir. Birinci örnek, kapsayıcı boyut olarak büyüdükçe metnin yeniden düzenlenmesidir. İkinci örnekte, metin büyüdükçe yeniden düzenlenmez. Modifier.skipToLookaheadSize() eklemek, büyüme sırasında yeniden düzenlemeyi önler.

Modifier.skipToLookahead() yok - "Lorem Ipsum" metninin yeniden aktığına dikkat edin

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

Klip ve yer paylaşımları

Compose'da paylaşılan öğeler oluşturulurken üzerinde düşünülen önemli bir nokta, bunların farklı composable'lar arasında paylaşım yapılabilmesi için, geçiş hedeftekiyle eşleşmeye başladığında composable'ın oluşturulmasının bir katman yer paylaşımına yükseltilmesidir. Böylece üst öğe sınırlarından ve katman dönüşümlerinden (ör. alfa ve ölçek) kaçar.

Öğe, paylaşılmayan diğer kullanıcı arayüzü öğelerinin üzerinde oluşturulur ve geçiş tamamlandıktan sonra öğe, yer paylaşımından kendi DrawScope öğesine bırakılacaktır.

Paylaşılan bir öğeyi şekle kırpmak için standart Modifier.clip() işlevini kullanın. sharedElement() öğesinden sonra yerleştir:

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şturulmadığından emin olmanız gerekiyorsa sharedElement() üzerinde clipInOverlayDuringTransition parametresini ayarlayabilirsiniz. clipInOverlayDuringTransition, varsayılan olarak iç içe yerleştirilmiş paylaşılan sınırlar için sharedBounds() üst öğesinden klip yolunu kullanır.

Alt çubuk veya kayan işlem düğmesi gibi belirli kullanıcı arayüzü öğelerinin, paylaşılan öğe geçişi sırasında her zaman üstte tutulabilmesi için Modifier.renderInSharedTransitionScopeOverlay() özelliğini kullanın. Bu değiştirici varsayılan olarak, paylaşılan geçişin etkin olduğu süre boyunca içeriği yer paylaşımında tutar.

Örneğin, Jetsnack'te, ekran görünene kadar BottomAppBar öğesinin paylaşılan öğenin üzerine yerleştirilmesi gerekir. Düzenleyiciyi composable'a eklemek onu yüksekte tutar.

Modifier.renderInSharedTransitionScopeOverlay() olmadan

Modifier.renderInSharedTransitionScopeOverlay() ile

Bazen, paylaşılmayan composable'ın geçişten önce diğer composable'ların üzerinde durmasını ve diğer composable'ların üstünde durmasını isteyebilirsiniz. Bu gibi durumlarda, paylaşılan öğe geçişi çalışırken composable'a animasyon eklemek 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şinde içeri ve dışarı kayan alt uygulama çubuğu

Paylaşılan öğenizin bir yer paylaşımında oluşturulmasını istemediğiniz nadir durumlarda, sharedElement() üzerindeki renderInOverlayDuringTransition öğesini false olarak ayarlayabilirsiniz.

Paylaşılan öğe boyutundaki değişiklikleri eşdüzey düzenlerine bildir

Varsayılan olarak sharedBounds() ve sharedElement(), düzen geçişi sırasında üst kapsayıcıya herhangi bir boyut değişikliği bildirmez.

Geçiş işlemi sırasında üst kapsayıcıya boyut değişiklikleri uygulamak için placeHolderSize parametresini PlaceHolderSize.animatedSize olarak değiştirin. Bu, öğ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

(Artan bir öğeye yanıt olarak listedeki diğer öğelerin nasıl azaldığına dikkat edin)