Shared Element Transition — bu nima, o'tishlarda umumiy elementlar

Muallif: IT Sectr Nashr etilgan: 2026-03-02 O'qish vaqti: 10 daq

Shared Element Transition — navigatsiya vaqtida umumiy element (tasvir, matn, karta) ikki ekran o'rtasida silliq harakatlanadigan va transformatsiyalanadigan animatsiya. Keskin o'tish o'rniga foydalanuvchi uzluksiz harakatni ko'radi: element A ekrandan B ekranga «oqadi», kontekst va vizual bog'lanishni saqlaydi. Material Design Guidelines (2026) ma'lumotlariga ko'ra, Shared Element Transition qabul qilinadigan samaradorlikni 35% ga oshiradi va navigatsiyani tushunishni 28% ga yaxshilaydi. Animatsiyaning boshqa turlari haqida umumiy animatsiya qo'llanmasida o'qing.

Asosiy

  • Shared Element Transition — navigatsiya vaqtida ikki ekran o'rtasida umumiy element animatsiyasi.
  • sharedElementEnterTransition — Android da umumiy element kirishini sozlash uchun XML atributi.
  • UIViewPropertyAnimator — iOS da UIViewController o'rtasida maxsus shared-animatsiyalar asosi.
  • Umumiy element Android da transitionName va iOS da tag yoki snapshot orqali o'rnatiladi.
  • Animatsiya ImageView, TextView, CardView, Button va noyob identifikatorga ega har qanday View bilan ishlaydi.

Shared Element Transition nima?

Shared Element Transition — bu bir yoki bir nechta vizual elementlarning oldingi ekrandan keyingi ekranga «ko'chadigan» ekran almashish animatsiyasi. Navigatsiya paytida tizim elementni manba ekranda snapshot qiladi, uning transformatsiyasini (pozitsiya, o'lcham, shakl, rang) yangi ekranda maqsadli holatga animatsiya qiladi. Natijada foydalanuvchi ikki ekranni alohida sahifalar emas, balki yagona makonning qismlari sifatida qabul qiladi.

Asosiy foydalanish stsenariylari: mahsulot kartasi → tafsilotli ekran (tasvir kattalashadi va yuqoriga o'tadi), tasvir galereyasi → ko'rish (tasvir butun ekranga silliq ochiladi), kontaktlar ro'yxati → profil (avatar va ism ko'chadi). To'g'ri ishlash uchun ikkala ekranda bir xil transitionName (Android) yoki snapshot identifikatori (iOS) bo'lgan View bo'lishi kerak.

Google I/O 2025 ma'lumotlariga ko'ra, Shared Element Transition mobil ilovalar uchun eng samarali UX naqshlaridan biri hisoblanadi: umumiy element animatsiyasini ko'rgan foydalanuvchilar o'tishdan keyin darhol qaytishni 22% kamroq qiladi. Biroq, haddan tashqari foydalanish (o'tish boshiga 3 dan ortiq shared element) effektni kamaytiradi va o'rta segment qurilmalarda FPS 40 dan pastga tushishiga olib kelishi mumkin.

Android da Shared Element Transition (Kotlin)

Android da Shared Element Transition FragmentTransaction.addSharedElement(view, transitionName) yoki ActivityOptions.makeSceneTransitionAnimation orqali amalga oshiriladi. Har bir View ga noyob android:transitionName beriladi — ikkala ekranda bir xil. Tizim avtomatik ravishda harakat (ChangeBounds), o'lcham o'zgarishi (ChangeTransform) va tasvir masshtablash (ChangeImageTransform) animatsiyasini yaratadi.

xml

<androidx.cardview.widget.CardView
    android:id="@+id/itemCard"
    android:transitionName="shared_element_@{item.id}"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <ImageView
        android:id="@+id/itemImage"
        android:transitionName="shared_image_@{item.id}" />
</androidx.cardview.widget.CardView>


<ImageView
    android:id="@+id/detailImage"
    android:transitionName="shared_image_@{item.id}"
    android:layout_width="match_parent"
    android:layout_height="300dp" />
kotlin
import androidx.core.app.ActivityOptionsCompat
import androidx.core.util.Pair
import androidx.fragment.app.FragmentTransaction

// Activity: Shared Element ActivityOptions orqali
val options = ActivityOptionsCompat.makeSceneTransitionAnimation(
    this,
    Pair(imageView, getString(R.string.transition_name_image)),
    Pair(titleView, getString(R.string.transition_name_title))
)
startActivity(intent, options.toBundle())

// Fragment: Shared Element FragmentTransaction orqali
val detailFragment = DetailFragment().apply {
    sharedElementEnterTransition = TransitionInflater.from(context)
        .inflateTransition(android.R.transition.move)
    sharedElementReturnTransition = TransitionInflater.from(context)
        .inflateTransition(android.R.transition.move)
}

supportFragmentManager.beginTransaction()
    .addSharedElement(imageView, imageView.transitionName)
    .addSharedElement(titleView, titleView.transitionName)
    .replace(R.id.container, detailFragment)
    .addToBackStack(null)
    .commit()

// O'tishni moslashtirish: ChangeBounds + ChangeImageTransform
detailFragment.sharedElementEnterTransition = TransitionSet().apply {
    ordering = TransitionSet.ORDERING_TOGETHER
    addTransition(ChangeBounds())
    addTransition(ChangeTransform())
    addTransition(ChangeImageTransform())
    duration = 400L
    interpolator = FastOutSlowInInterpolator()
}

Android muhim tafsilotlari: turli scaleType (centerCrop → fitCenter) bilan ImageView ni to'g'ri animatsiya qilish uchun ChangeImageTransform dan foydalaning — u ko'rsatish usulining o'zgarishini avtomatik animatsiya qiladi. Dumaloq burchakli View (CardView) uchun ChangeBounds qo'shing, u burchak radiusini outline orqali animatsiya qiladi. Matn animatsiyasi (shrift hajmi o'zgarishi) uchun ChangeTextTransform dan foydalaning. Shared element ekranlardan birida yo'qolsa yoki paydo bo'lsa — tizim avtomatik ravishda Fade qo'llaydi.

iOS da Shared Element Transition (Swift)

iOS da Android sharedElementEnterTransition ning o'rnatilgan analogi yo'q — shared-animatsiyalar UIViewControllerAnimatedTransitioning orqali UIViewPropertyAnimator yoki CASpringAnimation yordamida qo'lda amalga oshiriladi. Asosiy texnika: animateTransition(using:) ichida manba ekranning View ni oling, uning snapshot ini yarating, containerView ga qo'shing, asl nusxani yashiring va snapshot ni maqsadli pozitsiyaga animatsiya qiling. Tugaganda maqsadli View ni ko'rsating va snapshot ni o'chiring.

swift
import UIKit

"> Shared Element uchun custom animator
class SharedElementAnimator: NSObject, UIViewControllerAnimatedTransitioning {
    let fromView: UIView
    let toView: UIView
    let fromFrame: CGRect
    let toFrame: CGRect
    let isPresenting: Bool

    func transitionDuration(using ctx: UIViewControllerContextTransitioning?) -> TimeInterval {
        return 0.4
    }

    func animateTransition(using ctx: UIViewControllerContextTransitioning) {
        guard let toVC = ctx.viewController(forKey: .to),
              let fromVC = ctx.viewController(forKey: .from)
        else { return }

        let container = ctx.containerView

        if isPresenting {
            container.addSubview(toVC.view)
            toVC.view.layoutIfNeeded()
            toVC.view.alpha = 0
        }

        // Umumiy elementning snapshot i
        let snapshot = fromView.snapshotView(afterScreenUpdates: false)!
        snapshot.frame = isPresenting ? fromFrame : toFrame
        snapshot.layer.cornerRadius = isPresenting ? 12 : 0
        container.addSubview(snapshot)

        fromView.isHidden = true
        toView.isHidden = true

        UIView.animate(withDuration: transitionDuration(using: ctx),
                       delay: 0,
                       usingSpringWithDamping: 0.7,
                       initialSpringVelocity: 0) {
            snapshot.frame = self.isPresenting ? self.toFrame : self.fromFrame
            snapshot.layer.cornerRadius = self.isPresenting ? 0 : 12
            toVC.view.alpha = 1
        } completion: { _ in
            fromView.isHidden = false
            toView.isHidden = false
            snapshot.removeFromSuperview()
            ctx.completeTransition(!ctx.transitionWasCancelled)
        }
    }
}

// Hero — shared transitions soddalashtirish uchun kutubxona
// heroID ikkala ekranda mos keladi, Android dagi transitionName ga o'xshash
import Hero

imageView.hero.id = "itemImage"
imageView.hero.modifiers = [.spring(stiffness: 300, damping: 20)]
titleLabel.hero.id = "itemTitle"

UIViewPropertyAnimator — iOS 10+ da shared-animatsiyalar uchun afzal qilingan usul. UIView.animate dan farqli o'laroq, PropertyAnimator interaktiv boshqaruvni (fractionComplete) qo'llab-quvvatlaydi, bu shared transition ni swipe-back imo-ishorasi bilan integratsiya qilish imkonini beradi. Hero kutubxonasi (uchinchi tomon) uchun shared transition hero.id orqali o'rnatiladi — bu Android dagi transitionName ning analogi bo'lib, ekranlar o'rtasida pozitsiya, o'lcham, cornerRadius, zPosition va backgroundColor ni avtomatik animatsiya qiladi.

Jetpack Compose da Shared Element

Jetpack Compose da Shared Element Transition graphicsLayer modifikatori va SharedTransitionScope (Compose 1.7+) animatsiyasi orqali amalga oshiriladi. Har bir shared element noyob kalit bilan sharedElement() orqali belgilanadi. Tizim composable funksiyalar o'rtasida navigatsiya vaqtida pozitsiya, o'lcham, shakl, rang va kesish maskasining o'zgarishini avtomatik animatsiya qiladi. Android Developers Blog (2026) ma'lumotlariga ko'ra, Compose Shared Element Transition AnimatedContent, NavHost va maxsus konteynerlarni qo'llab-quvvatlaydi.

kotlin
import androidx.compose.animation.core.spring
import androidx.compose.animation.EnterTransition
import androidx.compose.animation.ExitTransition
import androidx.compose.animation.SharedTransitionLayout
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut

// SharedTransitionLayout — shared elementlar uchun konteyner
SharedTransitionLayout {
    val sharedTransitionState = remember { SharedTransitionState() }

    // Ekran A: ro'yxat
    LazyColumn {
        items(items) { item ->
            Card(
                modifier = Modifier.sharedElement(
                    state = sharedTransitionState,
                    key = SharedContentKey("image_${item.id}"),
                    boundsTransform = { _, _ ->
                        spring(dampingRatio = Spring.DampingRatioMediumBouncy)
                    }
                )
            ) {
                AsyncImage(model = item.imageUrl, contentDescription = null)
            }
        }
    }

    // Ekran B: tafsilotlar (element tanlanganda ko'rsatiladi)
    AnimatedContent(
        targetState = selectedItem,
        transitionSpec = {
            EnterTransition.None using SizeTransform(clip = false)
        }
    ) { item ->
        item?.let {
            Image(
                modifier = Modifier.sharedElement(
                    state = sharedTransitionState,
                    key = SharedContentKey("image_${it.id}")
                ),
                painter = rememberAsyncImagePainter(it.imageUrl),
                contentDescription = null,
                contentScale = ContentScale.FillWidth
            )
        }
    }
}

Compose 1.7+ SharedTransitionScope — eksperimental rejimda mavjud bo'lgan yangi API. NavHost da shared-animatsiyalarni qo'lda boshqarishni almashtiradi. Asosiy imkoniyatlar: maxsus animatsiya egri chizig'i uchun boundsTransform, dumaloq burchaklar uchun clipToBounds, qoplama tartibi uchun zIndex. Turli contentScale bilan tasvirlarni animatsiya qilish uchun SharedContentKey o'rami bilan Modifier.sharedElement dan foydalaning. Compose ning eski versiyalarini (< 1.7) qo'llab-quvvatlash uchun Google ning SharedTransitionScope kutubxonasidan foydalaning.

Optimallashtirish va tipik muammolar

Shared Element Transition platforma cheklovlari hisobga olinmasa, samaradorlik muammolariga olib kelishi mumkin. Android da asosiy muammo katta tasvirlar bilan (2048 px dan yuqori) ChangeImageTransform. iOS da — og'ir qatlamlar bilan (CAGradientLayer, ko'p sonli tugunli CAShapeLayer) snapshot. Yechim: shared-animatsiya uchun siqilgan tasvirlardan foydalaning va snapshot ni afterScreenUpdates: false bilan oling.

MuammoSababYechim
Sakrovchi animatsiyaO'tishdan oldin va keyin turlicha layout / og'ir snapshotPlaceholder dan foydalaning: yuklashda kichik oldindan ko'rishni ko'rsating
Shared element animatsiya qilinmayditransitionName ikkala ekranda mos kelmaydiXML/kodda transitionName ning aniq mosligini tekshiring
FPS < 40 Android daShared element murakkab View iyerarxiyasini o'z ichiga oladiFaqat ImageView ni shared qiling, butun CardView ni emas
iOS: snapshot artefaktlariMaskalar/animatsiyalar bilan qatlamda renderInContextdrawHierarchy(in:afterScreenUpdates: true) dan foydalaning
Compose: element ko'rinmaydiSharedTransitionLayout ikkala ekranni qamrab olmaydiSharedTransitionLayout ikkalasi uchun ota-ona bo'lishi kerak
kotlin
// Optimallashtirish: shared transition da tasvir uchun Placeholder
import androidx.core.widget.ImageViewCompat
import com.bumptech.glide.Glide

"> Navigatsiyadan oldin preview yuklash
Glide.with(context)
    .load(imageUrl)
    .override(300, 300) // Shared transition uchun o'lcham cheklovi
    .placeholder(R.drawable.placeholder)
    .into(imageView)

> O'tishdan keyin full-resolution kechiktirilgan yuklash
val detailImage = findViewById<ImageView>(R.id.detailImage)
detailImage.doOnPreDraw {
    Glide.with(context).load(imageUrl).into(detailImage)
}

// iOS: snapshot ni drawHierarchy bilan optimallashtirish
// snapshotView(afterScreenUpdates: false) — kutilayotgan yangilanishlarni e'tiborsiz qoldiradi, tezroq
// Murakkab View lar uchun: drawHierarchy(in: view.bounds, afterScreenUpdates: true)

Eng yaxshi amaliyotlar: bir o'tishda 3 tadan ortiq shared element qo'shmang — har bir qo'shimcha element render yukini oshiradi. Ro'yxatlar (RecyclerView/UICollectionView) uchun shared elementni butun ro'yxatga emas, balki bosilgan item ga qiling. Dumaloq burchakli kartalar uchun Android da clipToOutline yoki iOS da snapshot da cornerRadius dan foydalaning. Shared element ikkinchi ekranda ScrollView da bo'lsa, animatsiyani boshlashdan oldin layout tugashini kuting (view.doOnPreDraw).

Tez-tez beriladigan savollar

Bir o'tishda nechta shared elementni animatsiya qilish mumkin?

Bir o'tishda 3 shared elementdan ko'p bo'lmagan tavsiya etiladi. Har bir qo'shimcha element render yukini oshiradi va FPS tushishiga olib kelishi mumkin. Optimal: 1 tasvir + 1 matn (sarlavha). Android uchun har bir element addSharedElement(view, transitionName) orqali qo'shiladi. iOS uchun har bir snapshot containerView ga alohida qo'shiladi.

Shared Element Transition RecyclerView bilan ishlamaydi — nima qilish kerak?

transitionName onBindViewHolder da dinamik o'rnatilganligiga ishonch hosil qiling: holder.imageView.transitionName = «image_${position}». FragmentTransaction.addSharedElement uchun holder dan aniq View ni uzating. ActivityOptions uchun Pair.create(holder.imageView, holder.imageView.transitionName) dan foydalaning. Shared transition ni postponeEnterTransition() va startPostponedEnterTransition() orqali layout tugaguncha kechiktiring.

Fon rangining o'zgarishi bilan Shared Element Transition qanday qilinadi?

Android da: TransitionSet ga ChangeBackground qo'shing yoki captureStartValues va captureEndValues ni bekor qiluvchi maxsus Transition dan foydalaning. iOS da: snapshot ning backgroundColor ni yoki UIViewPropertyAnimator ni rang o'zgarishi bilan animatsiya qiling. Jetpack Compose da: Modifier.sharedElement Color transition orqali background ni avtomatik animatsiya qiladi. Kartalar uchun elevation ni ham animatsiya qiling — ro'yxatda 2dp dan tafsilotli ekranda 8dp gacha.

Shared Element Android da Jetpack Navigation bilan ishlaydimi?

Ha, Navigation Component bilan Shared Element NavOptions orqali qo'llab-quvvatlanadi: val navOptions = NavOptions.Builder().setEnterAnim(R.transition.move).applyNavOptions(fragment). Shared elementlarni uzatish uchun FragmentNavigatorExtras dan foydalaning: FragmentNavigatorExtras(view to transitionName). Navigation Compose uchun SharedTransitionScope (Compose 1.7+) dan Modifier.sharedElement dan foydalaning.

Shared Element Transition qanday disk raskadrovka qilinadi?

Android da Transition Debugging ni yoqing: adb shell setprop debug.transition 1 — logcat da shared elementlarni olish va animatsiya qilish haqida xabarlar paydo bo'ladi. Developer Options da «Show layout bounds» ni yoqib, oldin/keyin chegaralarni tekshiring. iOS da containerView dagi snapshot ni tekshirish uchun Debug View Hierarchy dan foydalaning. FPS kuzatuvi uchun Profile GPU Rendering (Android) yoki Core Animation instrument (iOS) dan foydalaning.

Xulosa

  • Shared Element Transition — vizual kontekstni saqlab, ekranlar o'rtasida umumiy element animatsiyasi.
  • Android: FragmentTransaction.addSharedElement yoki ActivityOptions.makeSceneTransitionAnimation.
  • iOS: UIViewControllerAnimatedTransitioning + snapshot + PropertyAnimator orqali maxsus amalga oshirish.
  • Jetpack Compose: Modifier.sharedElement SharedTransitionScope (Compose 1.7+).
  • FPS tushishini oldini olish uchun o'tish boshiga maksimum 3 shared element.
  • Turli scaleType bilan ImageView uchun ChangeImageTransform (Android) yoki snapshot (iOS) dan foydalaning.
  • Hero kutubxonasi (iOS) — Android dagi transitionName ga o'xshash hero.id bilan uchinchi tomon yechimi.

Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz

IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.

Loyihani muhokama qilish

Shuningdek o'qing