Flutter (और FlutterFlow) में एनिमेटेड स्प्लैश स्क्रीन
Charmotion टीम द्वारा · अपडेट:

Flutter का native splash, चाहे हाथ से सेट किया गया हो या flutter_native_splash से, बैकग्राउंड रंग पर एक स्थिर इमेज ही होता है। इसे एनिमेट करने के लिए वह splash रखें, अपनी पहली route में वही रंग और आइकन की वही position draw करें, वहाँ Rive या video intro चलाएँ, फिर आगे navigate करें। FlutterNativeSplash.preserve() और remove() से आप native splash को ठीक उसी समय hide कर सकते हैं जब intro तैयार हो।
मुख्य बातें
- flutter_native_splash platform की लॉन्च स्क्रीन बनाता है, जो static होती हैं; इसकी README के अनुसार Lottie अभी सपोर्ट नहीं है।
- एनिमेशन आपकी पहली route में होना चाहिए, native splash वाले बैकग्राउंड रंग पर ही draw किया हुआ।
preserve()native splash को रोके रखता है; intro फ़ाइल load होने परremove()कॉल करें।- Charmotion का
LaunchStateMachineकोई end event फ़ायर नहीं करता, इसलिए अगली स्क्रीन पर navigate करने से पहले 2.6 s इंतज़ार करें। - FlutterFlow की splash सेटिंग एक स्थिर इमेज होती है, जिसके साथ एक न्यूनतम अवधि तय होती है। इसलिए शुरुआती पेज पर एक RiveAnimation widget रखें।
पहले से कोई कैरेक्टर या लोगो है? अपने कैरेक्टर को असली ऐप स्क्रीन में देखें: स्प्लैश, ऑनबोर्डिंग, लोडिंग और एम्प्टी स्टेट स्क्रीन। यह फ़्री है, आपके ब्राउज़र में चलता है और कुछ भी अपलोड नहीं होता।
क्या flutter_native_splash को एनिमेट किया जा सकता है?
मोबाइल पर नहीं। यह package आपकी सेटिंग्स (एक रंग, एक इमेज, और Android 12 के विकल्प जैसे image और icon_background_color) से iOS और Android की native लॉन्च स्क्रीन बनाता है, और ये स्क्रीन Flutter engine शुरू होने तक एक स्थिर इमेज दिखाती हैं। इसके README में लिखा है कि GIF अब web पर सपोर्ट होते हैं और Lottie अभी सपोर्ट नहीं हैं (pub.dev)।
यह package की कोई ऐसी सीमा नहीं है जिससे बचा जा सके। iOS पर लॉन्च स्क्रीन बिना code के सिर्फ़ standard UIKit views इस्तेमाल कर सकती है। Android पर system splash में सिर्फ़ AnimatedVectorDrawable ही एनिमेट हो सकता है, और वह भी Android 12 और उसके बाद (देखें Android splash icon गाइड)। दोनों ही मामलों में Flutter उस समय चल ही नहीं रहा होता।
इसलिए तरीका वही है जो native ऐप में होता है: पहले एक static splash, फिर एक एनिमेटेड first route जो अपने पहले फ़्रेम पर बिल्कुल splash जैसा दिखे।
Flutter में एनिमेटेड first route कैसे बनाएँ?
Native splash को रोककर रखें, intro लोड करें, जैसे ही वह draw हो सके splash हटा दें, intro की लंबाई जितना इंतज़ार करें, फिर route बदल दें। यह rive package का मौजूदा API इस्तेमाल करता है (Rive):
import 'package:flutter/material.dart';
import 'package:flutter_native_splash/flutter_native_splash.dart';
import 'package:rive/rive.dart';
const bg = Color(0xFF0E1116); // same color as the native splash
Future<void> main() async {
final binding = WidgetsFlutterBinding.ensureInitialized();
FlutterNativeSplash.preserve(widgetsBinding: binding);
await RiveNative.init();
runApp(const MaterialApp(home: IntroPage()));
}
class IntroPage extends StatefulWidget {
const IntroPage({super.key});
@override
State<IntroPage> createState() => _IntroPageState();
}
class _IntroPageState extends State<IntroPage> {
File? file;
RiveWidgetController? controller;
@override
void initState() {
super.initState();
_run();
}
Future<void> _run() async {
final reduce = WidgetsBinding
.instance.platformDispatcher.accessibilityFeatures.disableAnimations;
if (!reduce) {
file = await File.asset('assets/launch.riv', riveFactory: Factory.rive);
if (file != null && mounted) {
setState(() => controller = RiveWidgetController(
file!,
stateMachineSelector: StateMachineSelector.byName('LaunchStateMachine'),
));
}
}
FlutterNativeSplash.remove();
// LaunchStateMachine fires no end event: wait for the 2.6 s intro.
if (controller != null) await Future.delayed(const Duration(milliseconds: 2600));
if (mounted) {
Navigator.of(context).pushReplacement(
MaterialPageRoute(builder: (_) => const HomePage()),
);
}
}
@override
void dispose() {
controller?.dispose();
file?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final still = MediaQuery.disableAnimationsOf(context) || controller == null;
return ColoredBox(
color: bg,
child: Center(
child: SizedBox(
width: 160,
height: 160,
child: still
? Image.asset('assets/icon_rest.png')
: RiveWidget(controller: controller!, fit: Fit.contain),
),
),
);
}
}
HomePage आपकी असली पहली स्क्रीन की जगह है। MediaQuery.disableAnimationsOf प्लेटफ़ॉर्म की reduce-motion सेटिंग दिखाता है (Flutter API)। यही flag _run में accessibilityFeatures के ज़रिए पढ़ा जाता है, क्योंकि initState में अभी कोई context नहीं होता।
क्या Flutter में इसकी जगह वीडियो intro इस्तेमाल कर सकते हैं?
हाँ। video_player (pub.dev) के साथ एक asset से controller बनाएँ, initialize() कॉल करें, then callback में native splash हटाएँ, और play करें। Controller को listen करें और जब position duration तक पहुँच जाए, तब navigate करें।
final video = VideoPlayerController.asset('assets/launch.mp4');
await video.initialize();
FlutterNativeSplash.remove();
video.addListener(() {
final v = video.value;
if (v.isInitialized && v.position >= v.duration) _goHome();
});
await video.setVolume(0);
await video.play();
सबसे आसान वीडियो intro एक opaque क्लिप है जिसका बैकग्राउंड बिल्कुल आपके splash रंग जैसा हो, और जो full-bleed या उसी रंग पर बीच में दिखाई जाए। अगर आइकन को किसी gradient या फ़ोटो के ऊपर रखना है, तो Flutter में ट्रांसपेरेंट बैकग्राउंड वाली .riv फ़ाइल को वीडियो से ज़्यादा आसानी से रखा जा सकता है। वीडियो detailed 3D या raster आइकन के लिए ठीक है, लेकिन बाद में वह स्टेट पर रिएक्ट नहीं कर सकता।
Splash से intro तक का बदलाव seamless कैसे बनाएँ?
- एक ही रंग। flutter_native_splash के
color(और अगर आप dark mode सपोर्ट करते हैं तोcolor_dark) को ही intro का बैकग्राउंड बनाएँ। - वही आइकन, वही जगह। Intro के पहले फ़्रेम या resting आइकन को splash इमेज के रूप में इस्तेमाल करें, उसी साइज़ में जिसमें intro उसे draw करता है। Android 12+ पर splash आइकन को गोले में crop किया जाता है, इसलिए जाँच लें कि crop किया गया आइकन भी मेल खाता है।
- Splash तभी हटाएँ जब सब तैयार हो। Intro फ़ाइल लोड होने के बाद
FlutterNativeSplash.remove()कॉल करें, ताकि यूज़र को कभी खाली फ़्रेम न दिखे। - इंतज़ार वाजिब रखें। यूज़र के विचारों का प्रवाह बनाए रखने की सीमा लगभग एक सेकंड है (NN/g)। लंबा intro सिर्फ़ पहले launch पर चलाएँ, और उसके बाद छोटा intro चलाएँ या बिल्कुल नहीं।
- मोशन कम करें सेटिंग का सम्मान करें। स्थिर आइकन दिखाएँ और तुरंत आगे बढ़ें।
FlutterFlow में एनिमेटेड splash कैसे जोड़ें?
FlutterFlow की splash सेटिंग्स (App Assets के अंदर) में fit और size विकल्पों के साथ एक अपलोड की गई इमेज, मिलीसेकंड में Min Duration, एक Background Color और इंजन लोड होते समय दिखने वाली खाली स्क्रीन के लिए एक Pre-loading Color होता है (FlutterFlow Docs)। Docs में वहाँ कोई एनिमेशन विकल्प नहीं बताया गया है, इसलिए इसे static हिस्सा मानें।
- Splash इमेज को अपने resting आइकन पर और दोनों रंगों को अपने ब्रांड बैकग्राउंड पर सेट करें।
- Min Duration छोटा रखें, क्योंकि यह हर launch को धीमा करता है।
- शुरुआती पेज के रूप में उसी बैकग्राउंड वाला एक intro पेज बनाएँ, और उसमें अपनी launch फ़ाइल के साथ एक RiveAnimation widget रखें (FlutterFlow Docs)।
- Page load पर 2.6 s इंतज़ार करें (Charmotion launch फ़ाइल के लिए) और बिना transition के अपने home पेज पर navigate करें।
अगर आपको ज़्यादा कंट्रोल चाहिए, तो FlutterFlow में Rive गाइड में स्टेट मशीन के नाम और custom code के बारे में बताया गया है। Charmotion आपके आइकन या मैस्कॉट की एक इमेज से LaunchStateMachine वाली .riv फ़ाइल, साथ में MP4 और ट्रांसपेरेंट वीडियो एक्सपोर्ट करता है।
Flutter में एनिमेटेड स्प्लैश स्क्रीन कैसे जोड़ें
- Static splash सेट करें. अपने ब्रांड रंग और resting आइकन के साथ flutter_native_splash इस्तेमाल करें।
- इसे रोककर रखें.
main()मेंFlutterNativeSplash.preserve(widgetsBinding: binding)कॉल करें। - Intro route बनाएँ. पहले route में वही रंग draw करें, और splash आइकन के साइज़ और जगह पर एक
RiveWidgetया वीडियो रखें। - हटाएँ और इंतज़ार करें. फ़ाइल लोड होते ही
FlutterNativeSplash.remove()कॉल करें, intro की लंबाई जितना इंतज़ार करें (Charmotion launch फ़ाइल के लिए 2.6 s), फिर home परpushReplacementकरें। - मोशन कम करें सेटिंग को संभालें. अगर
disableAnimationsचालू है, तो स्थिर आइकन दिखाएँ और तुरंत आगे बढ़ें।
अक्सर पूछे जाने वाले सवाल
क्या flutter_native_splash Lottie एनिमेशन चला सकता है?
नहीं। इसके README के अनुसार Lottie अभी सपोर्ट नहीं हैं, और GIF सपोर्ट सिर्फ़ web पर लागू है। iOS और Android पर native splash एक स्थिर इमेज है, इसलिए Lottie, Rive या वीडियो एनिमेशन को उसी बैकग्राउंड रंग पर अपने पहले route में चलाएँ।
Flutter में intro route होना चाहिए या overlay?
Route सबसे आसान है: एक IntroPage, जिसे pushReplacement से home पेज से बदल दिया जाता है। अगर आप चाहते हैं कि intro के दौरान ऐप नीचे build होता रहे, तो home पेज के ऊपर overlay भी काम करता है, लेकिन तब पक्का करें कि overlay सिर्फ़ दिखते समय ही इनपुट को ignore करे।
क्या Flutter में Android 12 के लिए अलग splash चाहिए?
flutter_native_splash में Android 12 के विकल्प इसलिए हैं क्योंकि वहाँ system splash आइकन को गोले में crop करता है और आइकन का बैकग्राउंड रंग इस्तेमाल कर सकता है। ऐसी इमेज दें जो crop होने पर भी साफ़ दिखे, वरना package आपके launcher आइकन का इस्तेमाल करेगा।
स्रोत
- flutter_native_splash, pub.dev
- Flutter runtime, Rive
- MediaQuery.disableAnimationsOf, Flutter API
- video_player, pub.dev
- App Assets (splash screen settings), FlutterFlow Docs
- RiveAnimation widget, FlutterFlow Docs
- Response Times: The 3 Important Limits, Nielsen Norman Group