मुख्य बिंदु
Hero Animation एक यूआइ एनिमेशन तकनीक है जिसमें एक शेयर्ड एलिमेंट स्रोत स्क्रीन से गंतव्य स्क्रीन पर सुचारू रूप से चलता है, अपनी पहचान बनाए रखता है। नाम एक “हीरो” की रूपक को दर्शाता है — एक मुख्य तत्व जो स्क्रीन के बीच एक स्क्रिप्टेड ट्रांज़िशन से गुज़रता है, उपयोगकर्ता का ध्यान आकर्षित करता है। मानक ट्रांज़िशन के विपरीत, Hero Animation दृश्य संबंध नहीं तोड़ता: उपयोगकर्ता तत्व का निरंतर प्रक्षेपवक्र देखता है, जो नेविगेशन पदानुक्रम की समझ में सुधार करता है।
Hero Animation की अवधारणा Material Design में सूची-विवरण स्क्रीन, गैलरी और कार्ड के लिए अनुशंसा के रूप में स्थापित है। एनिमेशन एल्गोरिदम तीन चरणों से बना है: स्रोत स्क्रीन पर, तत्व को हाइलाइट किया जाता है और एक निरपेक्ष स्थिति में स्थिर किया जाता है; ट्रांज़िशन के दौरान, यह लक्ष्य कंटेनर के अनुसार स्केल, चलता और आकार बदलता है; अंतिम स्क्रीन पर, तत्व नए लेआउट में एम्बेड किया जाता है। Material Design 3 के अनुसार, सही ढंग से लागू किया गया हीरो एनिमेशन गलत “वापस” बटन प्रेस की संख्या को 22% कम करता है।
Flutter में, Hero Animation Hero विजेट के माध्यम से लागू किया जाता है, जो एक अनिवार्य पैरामीटर tag — एक अद्वितीय पहचानकर्ता लेता है। Flutter स्वचालित रूप से स्रोत और गंतव्य मार्गों पर समान टैग वाले Hero विजेट की जोड़ी ढूंढता है और एनिमेशन शुरू करता है। Hero विजेट को मैन्युअल एनिमेशन प्रबंधन की आवश्यकता नहीं है — फ्रेमवर्क स्वतंत्र रूप से प्रक्षेपवक्र की गणना करता है और आंतरिक FlightShuttle ऑब्जेक्ट के माध्यम से रूपांतरण लागू करता है।
FlightShuttle एक अदृश्य “शटल” है जो ट्रांज़िशन के क्षण में, Hero विजेट की एक ओवरले कॉपी बनाता है, इसे निरपेक्ष समन्वय प्रणाली में रखता है, और प्रारंभिक स्थिति से अंतिम तक रूपांतरण (स्केल, ट्रांसलेट, रोटेट) को एनिमेट करता है। फ्लाइटशटल को flightShuttleBuilder प्रॉपर्टी के माध्यम से कस्टम कर्व पास किए जा सकते हैं, जिससे उड़ान प्रक्षेपवक्र को नियंत्रित किया जा सकता है: चाप में उड़ना, सीमाओं से उछलना, या आगमन से पहले धीमा होना। Flutter 3.16+ में, Hero clipRect और borderRadius को संरक्षित करते हुए एनिमेशन का समर्थन करता है, जो गोल कार्डों को आयताकार स्क्रीन में बदलने का प्रभाव देता है।
SwiftUI में, Hero Animation के समकक्ष matchedGeometryEffect मॉडिफ़ायर है, जो iOS 14 में पेश किया गया था। यह दो तत्वों को एक पहचानकर्ता (id) और एक namespace के माध्यम से जोड़ता है। Flutter के विपरीत, जहां Hero स्वचालित रूप से ट्रांज़िशन को इंटरसेप्ट करता है, SwiftUI को namespace की स्पष्ट घोषणा और दृश्य के दोनों भागों — स्रोत और गंतव्य — पर एक ही पदानुक्रम के भीतर या GeometryReader के माध्यम से मॉडिफ़ायर के आवेदन की आवश्यकता होती है।
matchedGeometryEffect एनिमेशन स्थिति, आकार, रोटेशन और कोने की त्रिज्या के रूपांतरण का समर्थन करता है। सहजता के लिए, withAnimation में एक Animation निर्दिष्ट किया जाता है। SwiftUI डिफ़ॉल्ट easeInOut कर्व के आधार पर मध्यवर्ती स्थितियों को स्वचालित रूप से इंटरपोलेट करता है। iOS 17+ में, TabView और NavigationStack के लिए matchedTransitionSource का समर्थन जोड़ा गया — मानक ट्रांज़िशन के लिए पूर्वनिर्धारित प्रक्षेपवक्र के साथ Hero Animation का एक सिस्टम एनालॉग।
Android में, Hero Animation को Shared Element Transition कहा जाता है और इसे ActivityOptions.makeSceneTransitionAnimation या FragmentTransaction.addSharedElement के माध्यम से लागू किया जाता है। प्रत्येक शेयर्ड एलिमेंट को XML में transitionName विशेषता या कोड के माध्यम से चिह्नित किया जाता है, और Android गतिविधियों के बीच एनिमेशन को संभालता है। Android 5.0 (API 21) से शुरू होकर, ट्रांज़िशन फ्रेमवर्क का हिस्सा बन गए; उससे पहले, ValueAnimator का उपयोग करके कस्टम एनिमेशन लिखने पड़ते थे।
Jetpack Compose में, Shared Element Transition Modifier.sharedElement और Modifier.sharedBounds मॉडिफ़ायर के माध्यम से AnimatedContent या SharedTransitionLayout (Compose BOM 2024.01 से उपलब्ध) के साथ लागू किया जाता है। View सिस्टम के विपरीत, Compose तत्वों को आलसी रूप से पुनर्खींचता है, इसलिए शेयर्ड एलिमेंट CompositionLocal में कैश किया जाता है। Compose स्क्रॉलऑफ़सेट संरक्षण के साथ सूची-से-विवरण एनिमेशन का भी समर्थन करता है — Hero ट्रांज़िशन के लिए एक महत्वपूर्ण क्षमता। Google I/O 2024 के अनुसार, Compose Shared Element Transition प्रत्यक्ष RenderNode प्रबंधन के कारण View संस्करण की तुलना में 15% तेज़ है।
Flutter में Hero Animation का एक बुनियादी उदाहरण: सूची स्क्रीन पर एक थंबनेल और विवरण स्क्रीन पर एक पूर्ण-स्क्रीन छवि। टैग image-hero दो विजेट को जोड़ता है, और FlightShuttle स्वचालित रूप से कार्ड से फुलस्क्रीन तक संक्रमण को एनिमेट करता है।
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,
),
),
),
);
}
}
मुख्य बिंदु दोनों स्क्रीन पर समान टैग (image-hero) है। Flutter मार्ग संक्रमण के दौरान टैग द्वारा Hero विजेट का मिलान करता है। यदि टैग भिन्न हैं, तो एनिमेशन शुरू नहीं होगा — तत्व बिना संक्रमण के नई स्क्रीन पर दिखाई देगा। टैग के लिए किसी भी प्रकार का उपयोग किया जा सकता है, लेकिन स्ट्रिंग्स सबसे विश्वसनीय विकल्प हैं।
NavigationStack के साथ SwiftUI में Hero Animation का एक उदाहरण। matchedGeometryEffect मॉडिफ़ायर सूची में छवि और विवरण स्क्रीन को एक namespace के माध्यम से जोड़ता है, और withAnimation एक सहज संक्रमण शुरू करता है।
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 matchedGeometryEffect पहचानकर्ता के लिए एक नाम स्थान बनाता है। दोनों तत्व एक ही id (“hero”) और एक साझा namespace का उपयोग करते हैं। जब isDetailShown टॉगल होता है, SwiftUI दो दृश्यों के बीच आकार, स्थिति और कोने की त्रिज्या के रूपांतरण को एनिमेट करता है, जिससे हीरो प्रभाव पैदा होता है। iOS 16+ के साथ मानक NavigationLink के लिए, navigationTransition(.hero) का उपयोग करें।
SharedTransitionLayout के साथ Jetpack Compose में Shared Element Transition का एक उदाहरण। sharedElement मॉडिफ़ायर नेविगेशन के दौरान स्क्रीन के बीच एक शेयर्ड एलिमेंट को एनिमेट करता है।
@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+) पदानुक्रम को लपेटता है, और “hero” कुंजी वाला sharedElement मॉडिफ़ायर प्रारंभिक और अंतिम तत्वों को जोड़ता है। AnimatedContent स्थिति को टॉगल करता है, और Compose स्वचालित रूप से छवि के आकार, स्थिति और आकृति को एनिमेट करता है। एक मुख्य लाभ bounds और clipBounds एनिमेशन के लिए समर्थन है, जो संक्रमण के दौरान कार्ड गोलाई प्रभाव प्रदान करता है।
अक्सर पूछे जाने वाले प्रश्न
हां, Hero Animation दोनों प्लेटफ़ॉर्म पर उपलब्ध है। iOS SwiftUI में matchedGeometryEffect या UINavigationController.transitioningDelegate का उपयोग करता है। Android ActivityOptions.makeSceneTransitionAnimation या Jetpack Compose में Modifier.sharedElement के साथ Shared Element Transition का उपयोग करता है। Flutter Hero विजेट के माध्यम से Hero Animation को लागू करता है, जो दोनों प्लेटफ़ॉर्म पर समान रूप से काम करता है।
हां, Hero Animation एकाधिक शेयर्ड एलिमेंट का समर्थन करता है। Flutter में, विभिन्न टैग के साथ कई Hero विजेट निर्दिष्ट करें। SwiftUI में, प्रत्येक तत्व पर विभिन्न पहचानकर्ताओं के साथ matchedGeometryEffect का उपयोग करें। सभी एनिमेशन समानांतर में चलते हैं — प्रत्येक तत्व अपने स्वयं के प्रक्षेपवक्र पर यात्रा करता है।
प्रदर्शन कार्यान्वयन पर निर्भर करता है। Flutter FlightShuttle RenderObject के माध्यम से छवियों को संसाधित करता है, 60fps प्राप्त करता है। SwiftUI matchedGeometryEffect वेक्टराइज़्ड है। बड़ी छवियों के लिए, Flutter में precacheImage या SwiftUI में prefetch का उपयोग करें — यह पहले संक्रमण पर देरी को समाप्त करता है। Android Compose को AsyncImage के माध्यम से विलंबित लोडिंग की आवश्यकता होती है।
एक मानक push संक्रमण पूरी स्क्रीन को स्लाइड करता है, कार्ड के ढेर का भ्रम पैदा करता है। Hero Animation दृश्य ध्यान को स्थिर करता है एक एकल तत्व पर — उपयोगकर्ता इसकी निरंतर गति देखता है, जो स्क्रीन के बीच संबंध की समझ में सुधार करता है। Push पदानुक्रमित नेविगेशन के लिए अच्छा है, Hero सामग्री पर जोर देने के लिए।
नहीं, Hero Animation अंतर्निहित उपकरणों के साथ लागू किया गया है। Flutter में, यह flutter/material.dart पैकेज से Hero विजेट है। SwiftUI में, यह matchedGeometryEffect मॉडिफ़ायर है। Android Jetpack Compose में, यह मानक Compose से SharedTransitionLayout और Modifier.sharedElement है। अतिरिक्त लाइब्रेरी केवल गैर-मानक प्रक्षेपवक्र या जटिल रूपांतरणों के लिए आवश्यक हैं।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें