خلاصہ
Hero Animation ایک UI اینیمیشن تکنیک ہے جس میں ایک مشترک عنصر مبادئی سکرین سے منزل کی سکرین پر آسانی سے حرکت کرتا ہے، اپنی شناخت برقرار رکھتا ہے۔ یہ نام ایک «ہیرو» کے استعارے کی عکاسی کرتا ہے — ایک اہم عنصر جو سکرین کے درمیان ایک سکرپٹ شدہ ٹرانزیشن سے گزرتا ہے، صارف کی تواجہ اپنی طرف کینچتا ہے۔ معیاری ٹرانزیشن کے برعکس، Hero Animation مرئی کڑی کو نہیں توڑتا: صارف عنصر کا مسلسل مسیر دیکھتا ہے، جو نیویگیشن درجہ بندی کی سمجھ میں بہتری کرتا ہے۔
Hero Animation کا تصور Material Design میں لسٹ-ڈیٹیل سکرین، گیلریز اور کارڈ کے لیے ایک سفارش کے طور پر قائم ہے۔ اینیمیشن الگورتھم تین مراحل پر مشتمل ہے: مبادئی سکرین پر، عنصر کو اجاگر کیا جاتا ہے اور ایک مطلق مقام پر مقرر کیا جاتا ہے؛ ٹرانزیشن کے دوران، یہ منزل کے کنٹینر کے مطابق اپنے پیمانے کو بدلتا ہے، حرکت کرتا ہے، اور شکل بدلتا ہے؛ آخری سکرین پر، عنصر نئے لی آؤٹ میں شامل کیا جاتا ہے۔ Material Design 3 کے مطابق، ایک صحیح طریقے سے نفذ شدہ ہیرو اینیمیشن غلط «واپس» بٹن کی دباؤں کی تعداد کو 22% تک کم کرتی ہے۔
Flutter میں، Hero Animation Hero واجٹ کے ذریعے نفذ کی جاتی ہے، جو ایک لازمی پیرامیٹر tag — ایک منفرد شناخت — لیتا ہے۔ Flutter خود بخود مبادئی اور منزل کے راسٹوں پر ایک ہی ٹیگ کے ساتھ Hero واجٹس کا جوڑا چھونتا ہے اور اینیمیشن شروع کرتا ہے۔ Hero واجٹ کو دستی اینیمیشن منیجمنٹ کی ضرورت نہیں ہے — فریم ورک آزادانہ مسیر کا حساب لگاتا ہے اور اندرونی FlightShuttle آبجیکٹ کے ذریعے تبدیل کا اطلاق کرتا ہے۔
FlightShuttle ایک پنہان «شٹل» ہے جو ٹرانزیشن کے لمحے، Hero واجٹ کی ایک اوورلی کاپی بناتا ہے، اسے ایک مطلق کوئرڈینیٹ سسٹم میں رکھتا ہے، اور تبدیل (پیمانہ، ترجمہ، گھماو) کو شروعی مقام سے حتمی مقام تک اینیمیٹ کرتا ہے۔ flightShuttleBuilder پراپرٹی کے ذریعے FlightShuttle کو کسٹم منحنیات پہنچائے جا سکتے ہیں، جو پرواز کے مسیر کو کنٹرول کرنے کی اجازت دیتا ہے۔ Flutter 3.16+ میں، Hero clipRect اور borderRadius کو محفوظ رکھتے ہوئے اینیمیشن کی حمایت کرتا ہے، جو گول کارڈوں کے مستطیل سکرینوں میں بدلنے کا اثر دیتا ہے۔
SwiftUI میں، Hero Animation کا مترادف iOS 14 میں متعارف شدہ matchedGeometryEffect موڈیفائر ہے۔ یہ ایک شناخت (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 scrollOffset کو محفوظ رکھتے ہوئے لسٹ سے تفصیل تک اینیمیشن کی بھی حمایت کرتا ہے — 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 Animation کو Hero واجٹ کے ذریعے نفذ کرتا ہے، جو دونوں پلیٹ فارمز پر ایک جیسا کام کرتا ہے۔
جی ہاں، 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 ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔
مزید پڑھیں