Transition (κινούμενο σχέδιο μετάβασης) — μηχανισμός οπτικής αλλαγής ενός περιεχομένου σε άλλο: οθονών, τμημάτων, προβολών ή καταστάσεων διεπαφής. Μια σωστά υλοποιημένη μετάβαση κατευθύνει την προσοχή του χρήστη, εξηγεί τη σχέση μεταξύ στοιχείων και καθιστά την πλοήγηση διαισθητική. Σύμφωνα με το Material Design Guidelines (2026), οι εφαρμογές με καλά σχεδιασμένες μεταβάσεις εμφανίζουν 22% υψηλότερη διατήρηση χρηστών στη δεύτερη συνεδρία. Διαβάστε περισσότερα για άλλους τύπους κινούμενων σχεδίων στον γενικό οδηγό κινούμενων σχεδίων.
Κύρια σημεία
Transition — είναι ένα κινούμενο σχέδιο που συμβαίνει όταν μια οπτική κατάσταση διεπαφής αντικαθίσταται από μια άλλη. Σε αντίθεση με το Property Animation (κινούμενο σχέδιο ιδιοτήτων ενός αντικειμένου), το Transition διαχειρίζεται ένα ολόκληρο σύνολο αλλαγών: εμφάνιση/εξαφάνιση στοιχείων, αλλαγή θέσης, μεγέθους και ιδιοτήτων τους σε μία μετάβαση. Το Transition λύνει το πρόβλημα της ομαλής αλλαγής περιεχομένου έτσι ώστε ο χρήστης να καταλαβαίνει τι μετακινήθηκε πού.
Στις κινητές πλατφόρμες, το Transition εφαρμόζεται σε τρία κύρια σενάρια: πλοήγηση μεταξύ οθονών (push, pop, modal present), αλλαγή τμημάτων (Android FragmentTransaction) και αλλαγή κατάστασης εντός οθόνης (άνοιγμα κάρτας, εναλλαγή καρτελών). Κάθε σενάριο απαιτεί τη δική του προσέγγιση: μεταβάσεις πλοήγησης — UIViewControllerAnimatedTransitioning σε iOS ή ActivityOptions σε Android, μεταβάσεις εντός οθόνης — Transition Framework ή UIView.transition.
Σύμφωνα με το Apple HIG (2026), η διάρκεια μιας τυπικής μετάβασης δεν πρέπει να υπερβαίνει τα 400–500 ms — οι μεγαλύτερες κινήσεις γίνονται αντιληπτές ως καθυστέρηση. Το Material Design συνιστά 300–350 ms για κινητές μεταβάσεις. Για μεγάλα στοιχεία (κάρτες, εικόνες), ο χρόνος μπορεί να αυξηθεί έως 500–600 ms χωρίς απώλεια αντιληπτής απόδοσης.
Οι τύποι μεταβάσεων χωρίζονται σε διάφορες κατηγορίες ανάλογα με το ποιο περιεχόμενο αλλάζει και πώς. Βασικοί τύποι: σταδιακό σβήσιμο (cross-fade) — σταδιακή εξαφάνιση του ενός και εμφάνιση του άλλου; ολίσθηση (slide) — η μία οθόνη φεύγει, η άλλη έρχεται; κλιμάκωση (scale/zoom) — ένα στοιχείο μεγαλώνει, ανοίγοντας μια λεπτομερή οθόνη. Οι συνδυασμένες μεταβάσεις συνδυάζουν πολλαπλά εφέ.
| Τύπος μετάβασης | Περιγραφή | iOS API | Android API |
|---|---|---|---|
| Cross-fade | Σταδιακό σβήσιμο: ένα περιεχόμενο εξαφανίζεται, ένα άλλο εμφανίζεται | UIView.transition(with:duration:options:.transitionCrossDissolve) | TransitionSet + Fade() |
| Slide | Ολίσθηση: το περιεχόμενο φεύγει/έρχεται οριζόντια ή κάθετα | CATransition(type: .push, subtype: .fromLeft) | Slide() / FragmentTransaction.setCustomAnimations |
| Scale / Zoom | Κλιμάκωση: το στοιχείο μεγαλώνει σε πλήρη οθόνη | UIViewPropertyAnimator με κινούμενο σχέδιο scale | Scale() + ActivityOptions.makeScaleUpAnimation |
| Explode | Έκρηξη: το περιεχόμενο διαλύεται σε κομμάτια κατά την εξαφάνιση | CATransition(type: .reveal) | Explode() (API 21+) |
| Fade-through | Σταδιακό σβήσιμο μέσω λευκής/μαύρης οθόνης | UIView.transition(with: .transitionCrossDissolve, με λευκό φόντο) | Fade() μέσω ChangeBounds |
Κανόνες Material Design: χρησιμοποιείτε έναν τύπο μετάβασης σε μία εφαρμογή για τη δημιουργία μιας ενιαίας οπτικής γλώσσας. Το slide συνιστάται για πλοήγηση μεταξύ οθονών ίδιου επιπέδου (master → detail), το cross-fade για αλλαγή περιεχομένου σε μία οθόνη (καρτέλες, εναλλαγή προβολής), το scale/zoom για μετάβαση από κάρτα σε λεπτομερή οθόνη (κάρτα προϊόντος → περιγραφή).
Σε iOS το UIView.transition είναι ο απλούστερος τρόπος κινούμενου σχεδίου αλλαγής περιεχομένου σε ένα View. Υποστηρίζει cross-dissolve, curl-up, curl-down, flip-from-left, flip-from-right. Για μεταβάσεις πλοήγησης μεταξύ UIViewController χρησιμοποιείται το UINavigationControllerDelegate με UIViewControllerAnimatedTransitioning — αυτό δίνει πλήρη έλεγχο στο κινούμενο σχέδιο push/pop.
import UIKit
// UIView.transition: αλλαγή εικόνας με cross-dissolve
UIView.transition(with: imageView,
duration: 0.4,
options: [.transitionCrossDissolve, .curveEaseInOut]
) {
self.imageView.image = UIImage(named: "new_image")
} completion: { _ in
print("Transition ολοκληρώθηκε")
}
// UIView.transition: αλλαγή δύο View
UIView.transition(from: firstView, to: secondView,
duration: 0.5,
options: [.transitionFlipFromRight, .showHideTransitionViews]
) { _ in
// firstView κρυμμένο, secondView εμφανίζεται
}
// CATransition για επίπεδο (χωρίς Auto Layout)
let transition = CATransition()
transition.type = .push
transition.subtype = .fromRight
transition.duration = 0.35
transition.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
view.layer.add(transition, forKey: "pushTransition")
UIViewPropertyAnimator — μια σύγχρονη εναλλακτική για προσαρμοσμένες μεταβάσεις σε iOS 10+. Σε αντίθεση με το UIView.transition, το PropertyAnimator υποστηρίζει παύση, ακύρωση και reverse (αντίστροφο κινούμενο σχέδιο), κάτι που είναι σημαντικό για διαδραστικές μεταβάσεις (swipe-to-go-back). Για κινούμενο σχέδιο μεταξύ UIViewController χρησιμοποιήστε το UIPercentDrivenInteractiveTransition σε συνδυασμό με το PropertyAnimator — αυτό είναι το τυπικό μοτίβο για διαδραστική πλοήγηση.
Σε Android το FragmentTransaction με setCustomAnimations είναι ο κύριος τρόπος κινούμενου σχεδίου μεταβάσεων μεταξύ Fragment. Παράμετροι: enter (κινούμενο σχέδιο εισόδου νέου Fragment), exit (κινούμενο σχέδιο εξόδου παλιού), popEnter και popExit — για πλοήγηση προς τα πίσω. Το FragmentTransaction υποστηρίζει κινούμενα σχέδια πόρων (R.anim) και Transition Framework (R.transition).
import androidx.fragment.app.FragmentTransaction
import androidx.transition.TransitionInflater
// FragmentTransaction με κινούμενα σχέδια πόρων
supportFragmentManager.beginTransaction()
.setCustomAnimations(
R.anim.slide_in_right, // enter
R.anim.slide_out_left, // exit
R.anim.slide_in_left, // popEnter
R.anim.slide_out_right // popExit
)
.replace(R.id.container, DetailFragment())
.addToBackStack(null)
.commit()
// FragmentTransaction με Transition Framework
val detailFragment = DetailFragment()
detailFragment.enterTransition = TransitionInflater.from(this)
.inflateTransition(R.transition.slide_right)
detailFragment.exitTransition = TransitionInflater.from(this)
.inflateTransition(R.transition.fade_out)
supportFragmentManager.beginTransaction()
.replace(R.id.container, detailFragment)
.addToBackStack(null)
.commit()
// ActivityOptions: κινούμενο σχέδιο κατά την εκκίνηση Activity
val options = ActivityOptions.makeScaleUpAnimation(
view, 0, 0, view.width, view.height
).toBundle()
startActivity(intent, options)
Βέλτιστες πρακτικές Android: Slide() — για αντικατάσταση Fragment σε πλοήγηση (enter = Slide(Gravity.END), exit = Slide(Gravity.START)). Fade() — για εμφάνιση/απόκρυψη επικαλύψεων και διαλόγων. Explode() — για τονισμένες μεταβάσεις (διαγραφή στοιχείου από λίστα). Για παλαιότερες συσκευές (API < 21) χρησιμοποιήστε πόρους R.anim ως εφεδρικό. Το Transition Framework δεν υποστηρίζει SurfaceView, TextureView, GLSurfaceView — για βίντεο και κάμερα χρησιμοποιήστε μόνο κινούμενα σχέδια μέσω R.anim.
UIViewControllerAnimatedTransitioning — πρωτόκολλο iOS για τη δημιουργία πλήρως προσαρμοσμένων κινούμενων σχεδίων μετάβασης μεταξύ ελεγκτών. Παρέχει πρόσβαση στο View κοντέινερ (transitionContext.containerView), στο View προέλευσης και προορισμού. Σε συνδυασμό με το UIPercentDrivenInteractiveTransition, αυτή η προσέγγιση επιτρέπει τη δημιουργία διαδραστικών μεταβάσεων με σύρσιμο δακτύλου.
import UIKit
"> Προσαρμοσμένος animator μετάβασης
class ScaleTransitionAnimator: NSObject, UIViewControllerAnimatedTransitioning {
let isPresenting: Bool
init(presenting: Bool) { self.isPresenting = presenting }
func transitionDuration(using ctx: UIViewControllerContextTransitioning?) -> TimeInterval {
return 0.4
}
func animateTransition(using ctx: UIViewControllerContextTransitioning) {
guard let toView = ctx.view(forKey: .to),
let fromView = ctx.view(forKey: .from)
else { return }
let container = ctx.containerView
let initialScale: CGAffineTransform = CGAffineTransform(scaleX: 0.8, y: 0.8)
let finalFrame = ctx.finalFrame(for: toView)
if isPresenting {
toView.transform = initialScale
toView.alpha = 0
toView.frame = finalFrame
container.addSubview(toView)
}
UIView.animate(withDuration: transitionDuration(using: ctx),
delay: 0,
usingSpringWithDamping: 0.7,
initialSpringVelocity: 0.3) {
if self.isPresenting {
toView.transform = .identity
toView.alpha = 1
fromView.transform = CGAffineTransform(scaleX: 0.9, y: 0.9)
fromView.alpha = 0
} else {
fromView.transform = initialScale
fromView.alpha = 0
}
} completion: { _ in
fromView.transform = .identity
ctx.completeTransition(!ctx.transitionWasCancelled)
}
}
}
// Εφαρμογή σε UINavigationControllerDelegate
extension MainViewController: UINavigationControllerDelegate {
func navigationController(
_ nc: UINavigationController,
animationControllerFor operation: UINavigationController.Operation,
from: UIViewController, to: UIViewController
) -> UIViewControllerAnimatedTransitioning? {
return ScaleTransitionAnimator(presenting: operation == .push)
}
}
Διαδραστικές μεταβάσεις: προσθέστε ένα UIPanGestureRecognizer στην οθόνη προέλευσης. Κατά την ενεργοποίηση της χειρονομίας, δημιουργήστε ένα UIPercentDrivenInteractiveTransition και καλέστε το update(CGFloat(percent)). Για ακύρωση όταν δεν επιτυγχάνεται το όριο (συνήθως 30%), καλέστε το cancel(). Αυτό το μοτίβο χρησιμοποιείται από προεπιλογή στο UINavigationController στη χειρονομία pop και στο UIScrollView με pagingEnabled. Για προσαρμοσμένες χειρονομίες, υλοποιήστε το UIViewControllerInteractiveTransitioning.
Transition Framework (android.transition) — είναι ένα δηλωτικό σύστημα κινούμενων σχεδίων που κινεί αυτόματα τις αλλαγές μεταξύ δύο σκηνών (Scene). Μια σκηνή είναι ένα σύνολο View με συγκεκριμένη κατάσταση. Κατά τη μετάβαση από τη Scene A στη Scene B, το Transition Framework αναλύει τη διαφορά και κινεί: αλλαγή θέσης (ChangeBounds), αλλαγή μεγέθους (ChangeClipBounds, ChangeTransform), εμφάνιση (Fade) και εξαφάνιση (Fade).
import android.transition.Scene
import android.transition.TransitionManager
import android.transition.TransitionSet
import android.transition.AutoTransition
import android.transition.ChangeBounds
import android.transition.Fade
// TransitionSet: συνδυασμός ChangeBounds + Fade
val transition = TransitionSet().apply {
ordering = TransitionSet.ORDERING_TOGETHER
addTransition(ChangeBounds())
addTransition(Fade(Fade.IN))
duration = 400L
interpolator = FastOutSlowInInterpolator()
}
// Μετάβαση μεταξύ σκηνών σε ViewGroup
val sceneRoot = findViewById<ViewGroup>(R.id.scene_root)
val scene1 = Scene.getSceneForLayout(sceneRoot, R.layout.scene_initial)
val scene2 = Scene.getSceneForLayout(sceneRoot, R.layout.scene_expanded)
"> AutoTransition χωρίς χειροκίνητη ρύθμιση
TransitionManager.go(scene2, AutoTransition().apply {
duration = 350L
})
// TransitionManager.beginDelayedTransition — χωρίς σκηνές
TransitionManager.beginDelayedTransition(sceneRoot, ChangeBounds())
itemView.layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT
itemView.requestLayout() "> Η αλλαγή layout γίνεται αυτόματα
ChangeBounds — η πιο συχνά χρησιμοποιούμενη μετάβαση σε Android, κινεί την αλλαγή θέσης και μεγέθους του View. Το ChangeTransform κινεί τα rotation και scale. Το ChangeImageTransform — για κινούμενο σχέδιο ImageView (centerCrop → fitCenter). Για σύνθετες μεταβάσεις με αλλαγή της δομής ιεραρχίας, χρησιμοποιήστε TransitionSet με ordering = ORDERING_SEQUENTIAL (τα κινούμενα σχέδια εκτελούνται διαδοχικά, όχι παράλληλα). Σύμφωνα με την τεκμηρίωση των Android Developers (2026), το Transition Framework υποστηρίζει όλα τα τυπικά View, αλλά δεν υποστηρίζει κινούμενο σχέδιο επιφάνειας (SurfaceView, TextureView, VideoView).
Συχνές ερωτήσεις
Animation — κινούμενο σχέδιο ιδιοτήτων ενός αντικειμένου (alpha, translation, scale). Transition — κινούμενο σχέδιο αλλαγής ενός συνόλου αντικειμένων ή καταστάσεων (τμήμα → τμήμα, σκηνή → σκηνή). Το Transition διαχειρίζεται πολλαπλές αλλαγές ταυτόχρονα: εμφάνιση, εξαφάνιση, μετακίνηση, αλλαγή μεγέθους — και κινεί αυτόματα τη διαφορά μεταξύ δύο καταστάσεων. Το Animation απαιτεί χειροκίνητη διαχείριση κάθε ιδιότητας.
Χρησιμοποιήστε το FragmentTransaction.setCustomAnimations με Transition Framework: fragment1.exitTransition = Fade(Fade.OUT), fragment2.enterTransition = Slide(Gravity.END). Για ακολουθία: setReorderingAllowed(true) — τα τμήματα θα αναδιαταχθούν για ομαλή παράλληλη μετάβαση. Για απλές περιπτώσεις, αρκούν τα slide_in_right / slide_out_left από το R.anim. Για πλοήγηση προς τα πίσω, καθορίστε popEnter και popExit.
Transition Framework κινεί μόνο ιδιότητες που δεν προκαλούν επανυπολογισμό της διάταξης. Για κινούμενο σχέδιο ύψους, χρησιμοποιήστε το ChangeBounds — κινεί αυτόματα την αλλαγή ορίων του View μεταξύ δύο καταστάσεων διάταξης. Καλέστε το TransitionManager.beginDelayedTransition(viewGroup, ChangeBounds()) πριν από την αλλαγή των LayoutParams. Εάν το ύψος αλλάζει μέσω WRAP_CONTENT, βεβαιωθείτε ότι το layout_height πριν και μετά είναι διαφορετικό — το ChangeBounds δεν θα λειτουργήσει εάν και οι δύο καταστάσεις είναι match_parent.
Χρησιμοποιήστε τον τροποποιητή .transition() με AnyTransition: .transition(.move(edge: .trailing).combined(with: .opacity)). Για προσαρμοσμένες μεταβάσεις, υλοποιήστε το AnyTransition.asymmetric(insertion: .move(edge: .trailing), removal: .move(edge: .leading)). Για κινούμενο σχέδιο εντός NavigationStack, χρησιμοποιήστε το .navigationTransition(.slide) σε iOS 18+. Το SwiftUI δεν υποστηρίζει UIViewControllerAnimatedTransitioning — μόνο δηλωτικές μεταβάσεις μέσω AnyTransition.
Χρησιμοποιήστε το Profile GPU Rendering (Android) ή το Core Animation Instrument (iOS). Για Android, προσθέστε προφίλ Transition μέσω adb shell setprop debug.transition.profiling 1 — στα αρχεία καταγραφής θα εμφανιστούν οι διάρκειες κάθε σταδίου μετάβασης. Σε iOS, ενεργοποιήστε το Slow Animations στον προσομοιωτή. Στόχοι μετρήσεων: διάρκεια < 400 ms, FPS >= 55, frame drops — όχι περισσότερα από 2 ανά μετάβαση. Για σύνθετες σκηνές με 15+ ταυτόχρονα κινούμενα View, χρησιμοποιήστε ChangeBounds με duration 300 ms.
Περίληψη
Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση
Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.
Διαβάστε επίσης