Mga Pangunahing Punto
Hero Animation — isang pamamaraan ng animasyon ng interface kung saan ang isang magkabahaging elemento ay maayos na gumagalaw mula sa pinagmulang screen patungo sa target na screen, na pinapanatili ang pagkakakilanlan nito. Ang pangalan ay sumasalamin sa metapora ng "bayani" — ang pangunahing elemento na dumadaan sa isang entablado transition sa pagitan ng mga screen, na nakakaakit ng atensyon ng user. Hindi tulad ng mga karaniwang transition, hindi sinisira ng Hero Animation ang visual na koneksyon: nakikita ng user ang patuloy na trajectory ng elemento, na nagpapabuti sa pag-unawa sa hierarchy ng nabigasyon.
Ang konsepto ng Hero Animation ay nakatanim sa Material Design bilang rekomendasyon para sa mga list-detail screen, gallery, at card. Ang algorithm ng animasyon ay binubuo ng tatlong yugto: sa pinagmulang screen, ang elemento ay naka-highlight at naayos sa ganap na posisyon; sa panahon ng transition, ito ay ni-scale, inilipat, at binago ang hugis ayon sa target na container; sa huling screen, ang elemento ay isinama sa bagong layout. Ayon sa Material Design 3, ang isang wastong ipinatupad na animasyon ng bayani ay nagbabawas ng bilang ng mga maling pag-click ng "bumalik" ng 22%.
Sa Flutter, ang Hero Animation ay ipinatupad sa pamamagitan ng Hero widget, na tumatanggap ng sapilitang parameter na tag — isang natatanging identifier. Awtomatikong hinahanap ng Flutter ang pares ng Hero na may parehong tag sa pinagmulan at target na ruta at inilulunsad ang animasyon. Ang Hero widget ay hindi nangangailangan ng manu-manong pamamahala ng animasyon — kinakalkula ng framework ang trajectory mismo at inilalapat ang pagbabago sa pamamagitan ng panloob na FlightShuttle object.
FlightShuttle — isang hindi nakikitang "shuttle" na sa sandali ng transition ay lumilikha ng overlay na kopya ng Hero widget, ipinoposisyon ito sa absolute coordinate system, at ina-animate ang transform (scale, translate, rotate) mula sa panimulang posisyon hanggang sa huling posisyon. Ang mga custom na curve ay maaaring ipasa sa FlightShuttle sa pamamagitan ng property na flightShuttleBuilder, na nagpapahintulot sa kontrol ng flight trajectory: paglipad sa isang arko, pagtalbog sa mga hangganan, o pagbagal bago dumating. Sa Flutter 3.16+, sinusuportahan ng Hero ang animasyon na may pagpapanatili ng clipRect at borderRadius, na nagbibigay ng epekto ng mga bilugan na card na nagbabago sa mga parihabang screen.
Sa SwiftUI, ang katumbas ng Hero Animation ay ang modifier na matchedGeometryEffect, na ipinakilala sa iOS 14. Ito ay nag-uugnay ng dalawang elemento sa pamamagitan ng identifier (id) at namespace. Hindi tulad ng Flutter kung saan awtomatikang ini-intercept ng Hero ang transition, ang SwiftUI ay nangangailangan ng malinaw na deklarasyon ng namespace at paglalapat ng modifier sa parehong bahagi ng eksena — pinagmulan at target — sa loob ng parehong hierarchy o sa pamamagitan ng GeometryReader.
Ang matchedGeometryEffect animasyon ay sumusuporta sa pagbabago ng posisyon, sukat, pag-ikot, at radius ng sulok (cornerRadius). Para sa kinis, ang Animation ay itinakda sa withAnimation. Awtomatikong ini-interpolate ng SwiftUI ang mga intermediate na estado batay sa default na easeInOut curve. Sa iOS 17+, idinagdag ang suporta para sa matchedTransitionSource para sa TabView at NavigationStack — isang system na analog ng Hero Animation na may paunang natukoy na trajectory para sa mga karaniwang transition.
Sa Android, ang Hero Animation ay tinatawag na Shared Element Transition at ipinatupad sa pamamagitan ng ActivityOptions.makeSceneTransitionAnimation o FragmentTransaction.addSharedElement. Ang bawat magkabahaging elemento ay minarkahan ng attribute na transitionName sa XML o sa pamamagitan ng code, at ang Android ang responsable para sa animasyon sa pagitan ng mga aktibidad. Mula sa Android 5.0 (API 21), ang mga transition ay naging bahagi ng framework; bago iyon, kailangang magsulat ng mga custom na animasyon sa pamamagitan ng ValueAnimator.
Sa Jetpack Compose, ang Shared Element Transition ay ipinatupad sa pamamagitan ng modifier na Modifier.sharedElement at Modifier.sharedBounds kasama ng AnimatedContent o SharedTransitionLayout (magagamit mula sa Compose BOM 2024.01). Hindi tulad ng View system, ang Compose ay tamad na nagre-redraw ng mga elemento, kaya ang magkabahaging elemento ay naka-cache sa CompositionLocal. Sinusuportahan din ng Compose ang animasyon ng listahan patungo sa detalye (list→detail) na may pagpapanatili ng scrollOffset — isang pangunahing kakayahan para sa Hero transitions. Ayon sa Google I/O 2024, ang Compose Shared Element Transition ay gumagana nang 15% mas mabilis kaysa sa View na bersyon dahil sa direktang pamamahala ng RenderNode.
Pangunahing halimbawa ng Hero Animation sa Flutter: isang thumbnail sa listahan screen at isang full-screen na imahe sa detalye screen. Ang tag na image-hero ay nag-uugnay sa dalawang widget, at ang FlightShuttle ay awtomatikong nag-a-animate ng transition mula sa card patungo sa full screen.
import 'package:flutter/material.dart';
class ListScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: ListView(
children: [
Hero(
tag: 'image-hero',
child: GestureDetector(
onTap: () {
Navigator.push(context,
MaterialPageRoute(
builder: (_) => DetailScreen(),
),
);
},
child: ClipRRect(
borderRadius: BorderRadius.circular(12),
child: Image.network(
'https://picsum.photos/200',
width: 100, height: 100,
fit: BoxFit.cover,
),
),
),
),
],
),
);
}
}
class DetailScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Detail')),
body: Center(
child: Hero(
tag: 'image-hero',
child: Image.network(
'https://picsum.photos/800',
width: 300, height: 400,
fit: BoxFit.cover,
),
),
),
);
}
}
Ang pangunahing punto — parehong tag (image-hero) sa parehong screen. Itinutugma ng Flutter ang Hero widget batay sa tag sa panahon ng route transition. Kung magkaiba ang mga tag, hindi magsisimula ang animasyon — lilitaw lang ang elemento sa bagong screen nang walang transition. Maaaring gamitin ang anumang uri para sa tag, ngunit ang mga string ay ang pinaka-maaasahang opsyon.
Halimbawa ng Hero Animation sa SwiftUI na may NavigationStack. Ang modifier na matchedGeometryEffect ay nag-uugnay ng larawan sa listahan at detalye screen sa pamamagitan ng namespace, at ang withAnimation ay naglulunsad ng maayos na transition.
import SwiftUI
struct HeroExampleView: View {
@Namespace private var heroNamespace
@State private var isDetailShown = false
var body: some View {
VStack {
if isDetailShown {
DetailView(namespace: heroNamespace)
.transition(.identity)
} else {
ListView(namespace: heroNamespace)
.transition(.identity)
}
}
.animation(Animation.easeInOut(duration: 0.4),
value: isDetailShown)
}
}
struct ListView: View {
let namespace: Namespace.ID
var body: some View {
Image("thumbnail")
.resizable()
.frame(width: 100, height: 100)
.cornerRadius(12)
.matchedGeometryEffect(id: "hero", in: namespace)
}
}
struct DetailView: View {
let namespace: Namespace.ID
var body: some View {
Image("thumbnail")
.resizable()
.frame(width: 300, height: 400)
.cornerRadius(0)
.matchedGeometryEffect(id: "hero", in: namespace)
}
}
@Namespace ay lumilikha ng namespace para sa identifier ng matchedGeometryEffect. Ang parehong elemento ay gumagamit ng parehong id (hero) at shared namespace. Kapag inilipat ang isDetailShown, ina-animate ng SwiftUI ang pagbabago ng laki, posisyon, at cornerRadius sa pagitan ng dalawang view, na lumilikha ng epekto ng bayani. Para sa karaniwang NavigationLink na may iOS 16+, gamitin ang navigationTransition(.hero).
Halimbawa ng Shared Element Transition sa Jetpack Compose na may SharedTransitionLayout. Ang modifier na sharedElement ay nag-a-animate ng magkabahaging elemento sa pagitan ng mga screen sa panahon ng nabigasyon.
@OptIn(ExperimentalSharedTransitionApi::class)
@Composable
fun HeroExample() {
SharedTransitionLayout {
var isDetail by remember { mutableStateOf(false) }
AnimatedContent(
targetState = isDetail,
transitionSpec = {
fadeIn() togetherWith fadeOut()
}
) { detail ->
if (detail) {
Box(
modifier = Modifier
.fillMaxSize()
.sharedElement(
state = rememberSharedContentState(key = "hero"),
animatedVisibilityScope = this
)
) {
AsyncImage(
model = "https://picsum.photos/800",
contentDescription = null,
modifier = Modifier.fillMaxSize()
)
}
} else {
Box(
modifier = Modifier
.size(100.dp)
.sharedElement(
state = rememberSharedContentState(key = "hero"),
animatedVisibilityScope = this
)
) {
AsyncImage(
model = "https://picsum.photos/200",
contentDescription = null,
modifier = Modifier.fillMaxSize()
)
}
}
}
}
}
Compose SharedTransitionLayout (Compose BOM 2024.01+) ay bumabalot sa hierarchy, at ang modifier na sharedElement na may key na hero ay nag-uugnay ng panimula at huling elemento. Binabago ng AnimatedContent ang estado, at awtomatikong ina-animate ng Compose ang laki, posisyon, at hugis ng larawan. Ang pangunahing bentahe — suporta para sa bounds at clipBounds animasyon, na nagbibigay ng epekto ng pagbilog ng card sa panahon ng transition.
Mga Madalas Itanong
Oo, ang Hero Animation ay available sa parehong platform. Sa iOS, ginagamit ang matchedGeometryEffect sa SwiftUI o UINavigationController.transitioningDelegate. Sa Android — transition ng ActivityOptions.makeSceneTransitionAnimation o Shared Element Transition sa Jetpack Compose na may Modifier.sharedElement. Ipinapatupad ng Flutter ang Hero Animation sa pamamagitan ng Hero widget na gumagana nang magkapareho sa parehong platform.
Oo, sinusuportahan ng Hero Animation ang maraming magkabahaging elemento. Sa Flutter, tukuyin ang ilang Hero na may iba't ibang tag. Sa SwiftUI, gamitin ang matchedGeometryEffect na may iba't ibang identifier sa bawat elemento. Lahat ng animasyon ay isinasagawa nang magkatulad — bawat elemento ay naglalakbay sa sarili nitong trajectory.
Ang pagganap ay nakadepende sa implementasyon. Pinoproseso ng Flutter FlightShuttle ang mga larawan sa pamamagitan ng RenderObject, na nagbibigay ng 60fps. Ang SwiftUI matchedGeometryEffect ay naka-vectorize. Para sa malalaking larawan, gamitin ang precacheImage sa Flutter o prefetch sa SwiftUI — inaalis nito ang mga pagkaantala sa unang transition. Ang Android Compose ay nangangailangan ng tamad na pag-load sa pamamagitan ng AsyncImage.
Ang karaniwang push transition ay gumagalaw sa buong screen, na lumilikha ng ilusyon ng isang stack ng mga card. Ang Hero Animation ay nakatutok ng visual na atensyon sa isang elemento — nakikita ng user ang patuloy na paggalaw nito, na nagpapabuti sa pag-unawa sa relasyon sa pagitan ng mga screen. Ang push ay mabuti para sa hierarchical nabigasyon, ang Hero — para sa pag-highlight ng nilalaman.
Hindi, ang Hero Animation ay ipinatupad gamit ang built-in na mga tool. Sa Flutter, ito ay Hero widget mula sa package na flutter/material.dart. Sa SwiftUI — ang modifier na matchedGeometryEffect. Sa Android Jetpack Compose — SharedTransitionLayout at Modifier.sharedElement mula sa standard na Compose. Ang mga karagdagang library ay kinakailangan lamang para sa hindi karaniwang trajectory o kumplikadong pagbabago.
Buod
Gagawa kami ng mobile application na turnkey
Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.
Basahin din