Transition: พื้นฐาน แอนิเมชันการเปลี่ยนในแอปมือถือ

ผู้แต่ง: IT Sectr เผยแพร่เมื่อ: 2026-03-02 เวลาอ่าน: 11 นาที

Transition (แอนิเมชันการเปลี่ยน) เป็นกลไกการเปลี่ยนแปลงทางภาพที่แทนที่เนื้อหาหนึ่งด้วยอีกเนื้อหาหนึ่ง: หน้าจอ แฟรกเมนต์ มุมมอง หรือสถานะอินเทอร์เฟซ การเปลี่ยนที่นำไปใช้อย่างถูกต้องจะชี้นำความสนใจของผู้ใช้ อธิบายความสัมพันธ์ระหว่างองค์ประกอบ และทำให้การนำทางเป็นไปอย่าง intuit ตาม Material Design Guidelines (2026) แอปที่มีการเปลี่ยนที่ออกแบบมาอย่างดีแสดงอัตราการรักษาผู้ใช้สูงขึ้น 22% ในเซสชันที่สอง เรียนรู้เพิ่มเติมเกี่ยวกับแอนิเมชันประเภทอื่นได้ใน คำแนะนำแอนิเมชันทั่วไป

ประเด็นสำคัญ

  • Transition — แอนิเมชันการเปลี่ยนเนื้อหาระหว่างหน้าจอ แฟรกเมนต์ หรือสถานะ
  • UIView.transition — API หลักสำหรับแอนิเมชันการเปลี่ยนใน iOS (UIKit)
  • FragmentTransaction.setCustomAnimations — การกำหนดค่าแอนิเมชันการเปลี่ยนระหว่าง Fragment ใน Android
  • Transition Framework (android.transition) — ระบบแอนิเมชันแบบประกาศของ Android สำหรับการเปลี่ยนจากซีนหนึ่งไปอีกซีน
  • UIViewControllerAnimatedTransitioning — โปรโตคอล iOS สำหรับการเปลี่ยนแบบกำหนดเองระหว่างคอนโทรลเลอร์

Transition คืออะไร?

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 มิลลิวินาที — แอนิเมชันที่ยาวกว่าจะถูกรับรู้ว่าล่าช้า Material Design แนะนำ 300–350 มิลลิวินาทีสำหรับการเปลี่ยนบนมือถือ สำหรับองค์ประกอบขนาดใหญ่ (การ์ด รูปภาพ) เวลาสามารถเพิ่มเป็น 500–600 มิลลิวินาทีโดยไม่สูญเสียประสิทธิภาพที่รับรู้ได้

ประเภทของแอนิเมชันการเปลี่ยน

ประเภทการเปลี่ยน แบ่งออกเป็นหลายหมวดหมู่ขึ้นอยู่กับว่าเนื้อหาใดเปลี่ยนแปลงและเปลี่ยนแปลงอย่างไร ประเภทพื้นฐาน: cross-fade — การหายไปอย่างราบรื่นของหนึ่งและการปรากฏของอีกหนึ่ง; slide — หน้าจอหนึ่งออกไปอีกหน้าจอหนึ่งเข้ามา; scale/zoom — องค์ประกอบขยายใหญ่ขึ้นเปิดหน้าจอรายละเอียด การเปลี่ยนแบบผสมผสานหลายเอฟเฟกต์เข้าด้วยกัน

ประเภทการเปลี่ยนคำอธิบายiOS APIAndroid API
Cross-fadeเฟด: เนื้อหาหนึ่งหายไป อีกเนื้อหาหนึ่งปรากฏUIView.transition(with:duration:options:.transitionCrossDissolve)TransitionSet + Fade()
Slideเลื่อน: เนื้อหาเข้า/ออกในแนวนอนหรือแนวตั้งCATransition(type: .push, subtype: .fromLeft)Slide() / FragmentTransaction.setCustomAnimations
Scale / Zoomซูม: องค์ประกอบขยายเป็นเต็มหน้าจอUIViewPropertyAnimator พร้อมแอนิเมชันสเกลScale() + ActivityOptions.makeScaleUpAnimation
Explodeระเบิด: เนื้อหาแตกเป็นชิ้นเมื่อหายไปCATransition(type: .reveal)Explode() (API 21+)
Fade-throughเฟดผ่านหน้าจอขาว/ดำUIView.transition(with: .transitionCrossDissolve, พื้นหลังสีขาว)Fade() ผ่าน ChangeBounds

กฎ Material Design: ใช้การเปลี่ยนประเภทเดียวภายในแอปเดียวเพื่อสร้างภาษาภาพที่ unified แนะนำ: slide สำหรับการนำทางระหว่างหน้าจอระดับเดียวกัน (master → detail), cross-fade สำหรับการเปลี่ยนเนื้อหาภายในหน้าจอเดียว (แท็บ การสลับมุมมอง), scale/zoom สำหรับการเปลี่ยนจากการ์ดไปยังหน้าจอรายละเอียด (การ์ดสินค้า → คำอธิบาย)

การเปลี่ยนใน iOS (Swift)

ใน iOS UIView.transition เป็นวิธีที่ง่ายที่สุดในการทำให้การเปลี่ยนแปลงเนื้อหาภายใน View เดียวเคลื่อนไหว รองรับ cross-dissolve, curl-up, curl-down, flip-from-left, flip-from-right สำหรับการเปลี่ยนนำทางระหว่าง UIViewController ให้ใช้ UINavigationControllerDelegate กับ UIViewControllerAnimatedTransitioning — ซึ่งให้การควบคุมแอนิเมชัน push/pop อย่างสมบูรณ์

swift
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 completed")
}

// 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 รองรับการหยุดชั่วคราว การยกเลิก และแอนิเมชันย้อนกลับ ซึ่งสำคัญสำหรับการเปลี่ยนแบบโต้ตอบ (ปัดเพื่อกลับ) สำหรับแอนิเมชันระหว่าง UIViewControllers ให้ใช้ UIPercentDrivenInteractiveTransition ร่วมกับ PropertyAnimator — นี่คือรูปแบบมาตรฐานสำหรับการนำทางแบบโต้ตอบ

การเปลี่ยนใน Android (Kotlin)

ใน Android FragmentTransaction กับ setCustomAnimations เป็นวิธีหลักในการทำให้การเปลี่ยนระหว่าง Fragment เคลื่อนไหว พารามิเตอร์: enter (แอนิเมชันเข้าของ Fragment ใหม่), exit (แอนิเมชันออกของ Fragment เก่า), popEnter และ popExit — สำหรับการนำทางกลับ FragmentTransaction รองรับทรัพยากรแอนิเมชัน (R.anim) และ Transition Framework (R.transition)

kotlin
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 เท่านั้น

การเปลี่ยน UIViewController แบบกำหนดเองใน iOS

UIViewControllerAnimatedTransitioning เป็นโปรโตคอล iOS สำหรับสร้างแอนิเมชันการเปลี่ยนระหว่างคอนโทรลเลอร์แบบกำหนดเองได้ทั้งหมด ให้การเข้าถึงคอนเทนเนอร์วิว (transitionContext.containerView) วิวต้นทางและวิวเป้าหมาย เมื่อรวมกับ UIPercentDrivenInteractiveTransition วิธีการนี้ช่วยให้สร้างการเปลี่ยนแบบโต้ตอบด้วยการเลื่อนนิ้วได้

swift
import UIKit

"> แอนิเมเตอร์การเปลี่ยนผ่านที่กำหนดเอง
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 สำหรับเจสเจอร์แบบกำหนดเอง ให้implement UIViewControllerInteractiveTransitioning

Transition Framework ใน Android: ซีนต่อซีน

Transition Framework (android.transition) เป็นระบบแอนิเมชันแบบประกาศที่ทำให้การเปลี่ยนแปลงระหว่างสองซีน (Scene) เคลื่อนไหวโดยอัตโนมัติ ซีนคือชุดของ Views ที่มีสถานะเฉพาะ เมื่อเปลี่ยนจากซีน A ไปยังซีน B Transition Framework จะวิเคราะห์ความแตกต่างและทำให้เคลื่อนไหว: การเปลี่ยนตำแหน่ง (ChangeBounds) การเปลี่ยนขนาด (ChangeClipBounds, ChangeTransform) การปรากฏ (Fade) และการหายไป (Fade)

kotlin
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 ทำให้การหมุนและสเกลเคลื่อนไหว ChangeImageTransform — สำหรับแอนิเมชัน ImageView (centerCrop → fitCenter) สำหรับการเปลี่ยนที่ซับซ้อนที่มีการเปลี่ยนแปลงโครงสร้างลำดับชั้น ให้ใช้ TransitionSet กับ ordering = ORDERING_SEQUENTIAL (แอนิเมชันทำงานตามลำดับ ไม่ใช่แบบขนาน) ตามเอกสารของ Android Developers (2026) Transition Framework รองรับ Views มาตรฐานทั้งหมด แต่ไม่รองรับแอนิเมชันพื้นผิว (SurfaceView, TextureView, VideoView)

คำถามที่พบบ่อย

ความแตกต่างระหว่าง Transition และ Animation คืออะไร?

Animation — ทำให้คุณสมบัติของวัตถุเดี่ยวเคลื่อนไหว (alpha, translation, scale) Transition — ทำให้การเปลี่ยนแปลงของชุดวัตถุหรือสถานะเคลื่อนไหว (fragment → fragment, scene → scene) Transition จัดการการเปลี่ยนแปลงหลายอย่างพร้อมกัน: การปรากฏ การหายไป การเคลื่อนที่ การเปลี่ยนขนาด — และทำให้ความแตกต่างระหว่างสองสถานะเคลื่อนไหวโดยอัตโนมัติ Animation ต้องการการจัดการด้วยตนเองสำหรับแต่ละคุณสมบัติ

วิธีสร้างการเปลี่ยนที่ราบรื่นระหว่าง Fragment ใน Android?

ใช้ 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 ไม่ทำให้การเปลี่ยนความสูงของ View เคลื่อนไหว — ต้องทำอย่างไร?

Transition Framework ทำให้เฉพาะคุณสมบัติที่ไม่ก่อให้เกิดการคำนวณเลย์เอาต์ใหม่เคลื่อนไหว สำหรับแอนิเมชันความสูง ให้ใช้ ChangeBounds — มันจะทำให้การเปลี่ยนแปลงขอบเขต View ระหว่างสองสถานะเลย์เอาต์เคลื่อนไหวโดยอัตโนมัติ เรียก TransitionManager.beginDelayedTransition(viewGroup, ChangeBounds()) ก่อนเปลี่ยน LayoutParams หากความสูงเปลี่ยนผ่าน WRAP_CONTENT ตรวจสอบให้แน่ใจว่า layout_height แตกต่างก่อนและหลัง — ChangeBounds จะไม่ทำงานหากทั้งสองสถานะเป็น match_parent

วิธีสร้างการเปลี่ยนแบบกำหนดเองใน SwiftUI?

ใช้ modifier .transition() กับ AnyTransition: .transition(.move(edge: .trailing).combined(with: .opacity)) สำหรับการเปลี่ยนแบบกำหนดเอง ให้implement AnyTransition.asymmetric(insertion: .move(edge: .trailing), removal: .move(edge: .leading)) สำหรับแอนิเมชันภายใน NavigationStack ให้ใช้ .navigationTransition(.slide) ใน iOS 18+ SwiftUI ไม่รองรับ UIViewControllerAnimatedTransitioning — เฉพาะการเปลี่ยนแบบประกาศผ่าน AnyTransition

วิธีวัดประสิทธิภาพของ Transition?

ใช้ Profile GPU Rendering (Android) หรือ Core Animation Instrument (iOS) สำหรับ Android ให้เปิด Transition Profiling ผ่าน adb shell setprop debug.transition.profiling 1 — บันทึกจะแสดงระยะเวลาของแต่ละขั้นตอนการเปลี่ยน ใน iOS ให้เปิด Slow Animations ในซิมิวเลเตอร์ ตัวชี้วัดเป้าหมาย: ระยะเวลา < 400 ms, FPS >= 55, การดรอปเฟรม — ไม่เกิน 2 ต่อการเปลี่ยน สำหรับซีนที่ซับซ้อนที่มี Views เคลื่อนไหวพร้อมกัน 15+ รายการ ให้ใช้ ChangeBounds ด้วยระยะเวลา 300 ms

สรุป

  • Transition — แอนิเมชันการเปลี่ยนเนื้อหาระหว่างหน้าจอ แฟรกเมนต์ หรือสถานะอินเทอร์เฟซ
  • UIView.transition (iOS) — API พื้นฐานสำหรับการเปลี่ยน cross-dissolve, flip, curl ภายใน View
  • UIViewControllerAnimatedTransitioning (iOS) — โปรโตคอลสำหรับการเปลี่ยนแบบกำหนดเองระหว่างคอนโทรลเลอร์
  • FragmentTransaction.setCustomAnimations (Android) — แอนิเมชันการเปลี่ยนระหว่าง Fragment
  • Transition Framework (android.transition) — ระบบซีนแบบประกาศ: ChangeBounds, Fade, Slide, Explode
  • ระยะเวลาที่แนะนำ: 300–400 ms สำหรับมือถือ สูงสุด 600 ms สำหรับองค์ประกอบขนาดใหญ่
  • การเปลี่ยนหนึ่งประเภทต่อแอปสำหรับภาษาภาพที่ unified (Material Design)

เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร

IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม