FlutterFlutter · Chapterبەش 9 · Lectureوانە 9.1

Splash Screensشاشەکانی دەستپێک

What a splash (launch) screen is and why apps have one; the native launch screen made with the flutter_native_splash package, including Android 12's rules and keeping it while the app loads; and a timed intro screen in Dart with initState, Timer and pushReplacement, written safely.

چییە و بۆچی هەیانە؛ ڕەسەن کە بە ⁦flutter_native_splash⁩ دروست دەکرێت، لەگەڵ یاساکانی ⁦Android 12⁩ و هێشتنەوەی تا بار دەبێت؛ و شاشەیەکی ناساندنی کاتدار لە بە initState، Timer و pushReplacement، بە شێوەیەکی سەلامەت.

21 min read20 خولەک خوێندنەوە · 17 stepsهەنگاو

What you will learnچی فێر دەبیت

  • Explain what a splash (launch) screen is, what it usually shows and why an app needs one.
  • Tell the native launch screen from a Dart intro screen, and say when each one is shown.
  • Make a native launch screen with flutter_native_splash, including the android_12 settings, and keep it while the app loads.
  • Write a timed intro screen with initState, Timer and pushReplacement that checks mounted and cancels its timer.
  • ڕوون بکەیتەوە چییە، زۆرجار چی پیشان دەدات و بۆچی پێویستی پێیەتی.
  • ڕەسەن لە شاشەی ناساندنی جیا بکەیتەوە و بڵێیت هەر یەکەیان کەی پیشان دەدرێت.
  • ڕەسەن بە ⁦flutter_native_splash⁩ دروست بکەیت، لەگەڵ ڕێکخستنەکانی ⁦android_12⁩ و بیهێڵیتەوە تا بار دەبێت.
  • شاشەیەکی ناساندنی کاتدار بە initState، Timer و pushReplacement بنووسیت کە mounted دەپشکنێت و کاتژمێرەکەی هەڵدەوەشێنێتەوە.

The first screen you seeیەکەم شاشە کە دەیبینیت

Tap the icon of an app. Before the app is ready, a simple screen appears for a moment, often a logo on a coloured background. This screen is called the splash screen or the launch screen.

دەست لە بدە. پێش ئەوەی ئامادە بێت، شاشەیەکی سادە بۆ ساتێک دەردەکەوێت، زۆرجار لۆگۆیەک لەسەر پاشبنەمایەکی ڕەنگاوڕەنگ. ئەم شاشەیە پێی دەوترێت .

Definitionپێناسە

The first screen shown while an app starts, usually its logo on a plain background. The phone shows a native launch screen first; an app may add its own timed intro screen after it.

یەکەم شاشەیە کە لە کاتی کردنەوەی ئەپێکدا پیشان دەدرێت، زۆرجار لۆگۆکەی لەسەر پاشبنەمایەکی سادە. مۆبایلەکە سەرەتا شاشەی دەستپێکی ڕەسەن پیشان دەدات؛ ئەپ دەتوانێت دوای ئەوە شاشەیەکی ناساندنی کاتدار زیاد بکات.

The course notes describe it like this: it is the first screen you see when you run an app. It is shown only for a short time, so it does not look like much. Its usual elements are the company's name and logo, or the app's title.

تێبینییەکانی وانەکە ئاوا باسی دەکەن: یەکەم شاشەیە کە کاتێک کار پێ دەکەیت دەیبینیت. تەنها بۆ ماوەیەکی کورت پیشان دەدرێت، بۆیە شتێکی زۆری تێدا نییە. بەشە باوەکانی ناو و لۆگۆی کۆمپانیاکە یان ناونیشانی .

Animation in three frames. 1: a phone's home screen with app icons; a finger taps the teal Class Notes icon. 2: the whole screen turns teal with a white book logo in the middle, labelled 'native launch screen: drawn by Android or iOS while Flutter starts'. 3: the app's first Flutter screen appears, with an app bar 'Class Notes' and the text 'Welcome!', labelled 'Flutter's first frame: the launch screen goes away'.
Animation in three frames. 1: a phone's home screen with app icons; a finger taps the teal Class Notes icon. 2: the whole screen turns teal with a white book logo in the middle, labelled 'native launch screen: drawn by Android or iOS while Flutter starts'. 3: the app's first Flutter screen appears, with an app bar 'Class Notes' and the text 'Welcome!', labelled 'Flutter's first frame: the launch screen goes away'.
From a tap on the icon to the app's first screen.لە دەستلێدان لە تا یەکەم شاشەی .CêIT
Quick checkپشکنینی خێراWhat does a splash screen usually show? زۆرجار چی پیشان دەدات؟

The first screen you seeیەکەم شاشە کە دەیبینیت

Why apps need a splash screenبۆچی ئەپەکان پێویستیان بە شاشەی دەستپێک هەیە

Starting an app takes time, even on a fast phone. Several things happen one after the other:

دەستپێکردنی کاتی دەوێت، تەنانەت لەسەر مۆبایلێکی خێراش. چەند شتێک یەک لە دوای یەک ڕوو دەدەن:

  1. The operating system starts the app's process.
  2. Flutter loads its engine.
  3. Your Dart code runs main(), then runApp() builds the first screen.
  4. Flutter draws its first frame: the first picture of your app on the screen.
  1. پرۆسەی دەست پێ دەکات.
  2. بزوێنەرەکەی بار دەکات.
  3. کۆدی main() جێبەجێ دەکات، پاشان runApp() یەکەم شاشە دروست دەکات.
  4. یەکەم دیمەن (first frame) دەکێشێت: یەکەم وێنەی لەسەر ڕووکاری مۆبایلەکە.

Without a splash screen the user would stare at a blank or black screen during these steps. The splash screen fills the gap, so the phone answers the tap at once. It should be brief: for phones, Android's guide recommends that even an animated launch icon last no longer than one second (1,000 ms).

بەبێ ، لە ماوەی ئەم هەنگاوانەدا تەماشای شاشەیەکی بەتاڵ یان ڕەش دەکات. ئەم بۆشاییە پڕ دەکاتەوە، بۆیە مۆبایلەکە یەکسەر وەڵامی دەستلێدانەکە دەداتەوە. دەبێت کورت بێت: ڕێنماییەکانی Android بۆ مۆبایل ئامۆژگاری دەکەن کە تەنانەت لە یەک چرکە ⁦(1,000 ms)⁩ زیاتر نەبێت.

Quick checkپشکنینی خێراWhy does an app show a splash screen?بۆچی پیشان دەدات؟

The first screen you seeیەکەم شاشە کە دەیبینیت

A glass of water at the tea houseپەرداخێک ئاو لە چایخانە

A glass of water at the tea houseپەرداخێک ئاو لە چایخانە

You sit down in a tea house. The tea needs a few minutes to brew, but the waiter puts a glass of water on your table at once. You know you have been seen and that your tea is coming. A splash screen is that glass of water: the app is not ready yet, but the user sees right away that it has started.

لە چایخانەیەک دادەنیشیت. چاکە چەند خولەکێکی دەوێت تا دەم بکێشێت، بەڵام چایچییەکە یەکسەر پەرداخێک ئاو لەسەر مێزەکەت دادەنێت. دەزانیت بینراویت و چاکەت لە ڕێگادایە. ئەو پەرداخە ئاوەیە: هێشتا ئامادە نییە، بەڵام یەکسەر دەبینێت کە دەستی پێ کردووە.

Where the analogy stops workingسنووری ئەم نموونەیە

Nobody wants to drink water for half an hour. A splash screen that stays too long, or that only exists to show a logo, makes the app feel slow.

کەس نایەوێت نیو کاتژمێر ئاو بخواتەوە. کە زۆر بمێنێتەوە، یان تەنها بۆ پیشاندانی لۆگۆیەک هەبێت، وا دەکات خاو دیار بێت.

Quick checkپشکنینی خێراIn the analogy, what is like the glass of water that arrives while the tea is brewing?لە نموونەکەدا، چی وەک ئەو پەرداخە ئاوەیە کە لە کاتی دەمکێشانی چاکەدا دێت؟

Two kinds: native launch screen and Dart intro screenدوو جۆر: شاشەی دەستپێکی ڕەسەن و شاشەی ناساندنی Dart

The notes give two methods for making a splash screen. They do not make the same thing, and it helps to keep them apart:

تێبینییەکان دوو ڕێگا بۆ دروستکردنی دەدەن. هەردووکیان هەمان شت دروست ناکەن و باشە لێک جیایان بکەینەوە:

PointخاڵNative launch screen ڕەسەنDart intro screenشاشەی ناساندنی
Made withبە چی دروست دەکرێتAndroid and iOS settings files; the flutter_native_splash package writes them for you (the notes' method 2) ڕێکخستنی Android و iOS؛ ⁦flutter_native_splash⁩ بۆت دەیاننووسێت (ڕێگای دووەمی تێبینییەکان)An ordinary Flutter screen with a Timer or Future.delayed (the notes' method 1)شاشەیەکی ئاسایی Flutter بە Timer یان Future.delayed (ڕێگای یەکەمی تێبینییەکان)
Shownکەی پیشان دەدرێتFrom the tap on the icon until Flutter draws its first frameلە دەستلێدان لە تا یەکەم دیمەن دەکێشێتAfter the first frame, for as long as your code decidesدوای یەکەم دیمەن، بۆ ئەو ماوەیەی کۆدەکەت بڕیاری دەدات
Can it run Dart code?دەتوانێت کۆدی جێبەجێ بکات؟No: Flutter is not running yet. It is only a colour and a picture.نەخێر: هێشتا کار ناکات. تەنها ڕەنگێک و وێنەیەکە.Yes: it is a normal widget with animations, text and buttons.بەڵێ: ئاساییە بە ، دەق و .
Needed?پێویستە؟Every app has one. A new Flutter project already has a plain white one on Android and a blank one on iOS.هەموو هەیەتی. پڕۆژەیەکی نوێی Flutter پێشتر یەکێکی سپیی سادەی لەسەر Android و یەکێکی بەتاڵی لەسەر iOS هەیە.Optionalهەڵبژاردەییە
A timeline from left to right. At the start a finger taps the app icon. A long teal bar labelled 'native launch screen (Android or iOS draws it)' covers three steps written under it: the system starts the app's process, Flutter loads its engine, main() and runApp() build the first screen. Then a marker 'Flutter's first frame' where the native screen disappears. After it a dashed, optional bar 'Dart intro screen (optional; your Timer decides how long)', then a bar 'home screen'. A note says to keep it brief: Android advises at most 1 second for the launch icon animation.هێڵێکی کات لە چەپەوە بۆ ڕاست. لە سەرەتادا پەنجەیەک لە ئایکۆنی ئەپەکە دەدات. شریتێکی درێژی سەوز بە ناونیشانی «شاشەی دەستپێکی ڕەسەن (Android یان iOS دەیکێشێت)» سێ هەنگاو دادەپۆشێت کە لە ژێریدا نووسراون: سیستەمەکە پرۆسەی ئەپەکە دەست پێ دەکات، Flutter بزوێنەرەکەی بار دەکات، main() و runApp() یەکەم شاشە دروست دەکەن. پاشان نیشانەیەک: «یەکەم دیمەنی Flutter» کە شاشە ڕەسەنەکە لەوێدا لادەچێت. دوای ئەو شریتێکی پچڕپچڕی هەڵبژاردەیی: «شاشەی ناساندنی Dart (هەڵبژاردەیی؛ Timerـەکەت ماوەکەی دیاری دەکات)»، پاشان شریتی «شاشەی سەرەکی». تێبینییەک دەڵێت کورتی بکەرەوە: Android ئامۆژگاری دەکات ئەنیمەیشنی ئایکۆنەکە لە یەک چرکە زیاتر نەبێت.
The native launch screen covers the start-up; a Dart intro screen, if you add one, comes after the first frame. ڕەسەن ماوەی دەستپێکردن دادەپۆشێت؛ شاشەی ناساندنی ، ئەگەر زیادی بکەیت، دوای یەکەم دیمەن دێت.CêIT

Apple requires every app on the App Store to provide a launch screen (an Xcode storyboard). A Dart intro screen is extra: add one only when it has a reason, for example a short animation of your logo.

Apple داوا دەکات هەموو لە ⁦App Store⁩ هەبێت (storyboardـێکی Xcode). شاشەی ناساندنی زیادەیە: تەنها کاتێک زیادی بکە کە هۆکارێکی هەبێت، بۆ نموونە کورتی لۆگۆکەت.

Quick checkپشکنینی خێراWhich screen is on the display while Flutter's engine is still loading?کاتێک بزوێنەری هێشتا بار دەبێت، کام شاشە لەسەر ڕووکارەکەیە؟

Method 2: a native launch screen with flutter_native_splashڕێگای دووەم: شاشەی دەستپێکی ڕەسەن بە ⁦flutter_native_splash⁩

A native launch screen is described in Android and iOS files: styles and pictures in the android/ folder, a storyboard in the ios/ folder, and index.html for the web. You could edit them by hand, but the flutter_native_splash package writes all of them from a few lines in pubspec.yaml.

ڕەسەن لە Android و iOSـدا وەسف دەکرێت: ستایل و وێنە لە android/، storyboardـێک لە ios/ و index.html بۆ وێب. دەتوانیت بە دەست دەستکارییان بکەیت، بەڵام ⁦flutter_native_splash⁩ هەموویان لە چەند دێڕێکی pubspec.yamlـەوە دەنووسێت.

Making a native launch screenدروستکردنی شاشەی دەستپێکی ڕەسەن
  1. Add the packageکتێبخانەکە زیاد بکە

    Run flutter pub add dev:flutter_native_splash. It adds the package to dev_dependencies, as in the notes: a tool you run while developing, not needed inside the finished app. (If your code will call preserve() and remove(), shown later, put it in dependencies instead, as the package README does.) Writing the line in pubspec.yaml yourself and running flutter pub get does the same.

    فەرمانی flutter pub add dev:flutter_native_splash جێبەجێ بکە. دەخاتە ناو dev_dependencies، وەک تێبینییەکان: ئامرازێکە لە کاتی گەشەپێداندا بەکاری دەهێنیت و لەناو تەواوبووەکەدا پێویست نییە. (ئەگەر کۆدەکەت بانگی preserve() و remove() دەکات، کە دواتر دەیانبینیت، لە جیاتی ئەوە بیخە ناو dependencies؛ READMEـی ئاوا دەکات.) ئەگەر خۆت دێڕەکە لە pubspec.yamlـدا بنووسیت و flutter pub get جێبەجێ بکەیت، هەمان کار دەکات.

  2. Write the settingsڕێکخستنەکان بنووسە

    Add a flutter_native_splash: section to pubspec.yaml with a colour and, if you want, a picture.

    بەشێکی flutter_native_splash: بۆ pubspec.yaml زیاد بکە، بە ڕەنگێک و ئەگەر بتەوێت وێنەیەک.

  3. Generate the filesفایلەکان دروست بکە

    Run dart run flutter_native_splash:create. The package writes the Android, iOS and web files. Run it again after every change to the settings.

    فەرمانی dart run flutter_native_splash:create جێبەجێ بکە. Android، iOS و وێب دەنووسێت. دوای هەر گۆڕانکارییەک لە ڕێکخستنەکاندا دووبارە جێبەجێی بکەرەوە.

  4. Run the app againئەپەکە دووبارە کار پێ بکەرەوە

    Stop the app and start it again. Hot reload cannot show the change, because the launch screen is native, not Dart.

    ڕابگرە و دووبارە دەستی پێ بکەرەوە. ناتوانێت گۆڕانکارییەکە پیشان بدات، چونکە ڕەسەنە، نەک .

The commandsفەرمانەکانBASHType in a terminalلە تێرمیناڵدا بینووسە
$ flutter pub add dev:flutter_native_splash
$ dart run flutter_native_splash:create
$ dart run flutter_native_splash:remove   # back to Flutter's plain default
Quick checkپشکنینی خێراYou changed the colour in the flutter_native_splash: section. What must you do before you can see it?ڕەنگەکەت لە بەشی flutter_native_splash:ـدا گۆڕی. پێش ئەوەی بیبینیت چی بکەیت؟

Flutter Native Splash Screen Detailed Setup Guide | 2024 EditionFlutterCraft · Englishئینگلیزی · 133K viewsبینین · 3.4K likesلایک

Make a native launch screen with flutter_native_splash: colour, logo, Android 12 rules, dark mode, and keeping it while the app loads.

دروستکردنی ڕەسەن بە flutter_native_splash: ڕەنگ، لۆگۆ، یاساکانی ⁦Android 12⁩، و هێشتنەوەی تا بار دەبێت.

The whole 10-minute guide: splash vs Flutter screens (0:16), package setup (0:51), Android 12+ (5:04), dark mode (6:31), showing the splash during initialisation (7:25).

هەموو فێرکارییە ⁦10⁩ خولەکییەکە: بەرامبەر شاشەکانی ⁦(0:16)⁩، ئامادەکردنی پاکێجەکە ⁦(0:51)⁩، ⁦Android 12+ (5:04)⁩، ⁦(6:31)⁩ و پیشاندانی تا ئامادە دەبێت ⁦(7:25)⁩.

Method 2: a native launch screen with flutter_native_splashڕێگای دووەم: شاشەی دەستپێکی ڕەسەن بە ⁦flutter_native_splash⁩

The notes' settings, updatedڕێکخستنەکانی تێبینییەکان، نوێکراوە

Step 2 is the flutter_native_splash: section. Here are the notes' settings, updated for today:

هەنگاوی دووەم بەشی flutter_native_splash:ـە. ئەمانە ڕێکخستنەکانی تێبینییەکانن، نوێکراوە بۆ ئەمڕۆ:

The notes' settings, updatedڕێکخستنەکانی تێبینییەکان، نوێکراوەpubspec.yamlYAML
dev_dependencies:
  flutter_native_splash: ^2.4.8

flutter_native_splash:
  color: "#42a5f5"
  image: assets/splash.png
  android_gravity: center
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 1-2

The package as a development tool. ^2.4.8 means version 2.4.8 or newer, below 3.0.0.

وەک ئامرازێکی گەشەپێدان. ^2.4.8 واتە ⁦2.4.8⁩ یان نوێتر، لە خوار ⁦3.0.0⁩.

Lineدێڕی 4

The section the package reads. It starts at the left edge, not inside flutter:.

ئەو بەشەی دەیخوێنێتەوە. لە لێواری چەپەوە دەست پێ دەکات، نەک لەناو flutter:ـدا.

Lineدێڕی 5

The background colour (here a light blue). The quotes are needed because # starts a comment in YAML.

ڕەنگی پاشبنەما (لێرەدا شینێکی کاڵ). کەوانە بچووکەکان پێویستن چونکە لە # دەست پێ دەکات.

Lineدێڕی 6

A PNG picture in the centre. The file must exist at this path.

وێنەیەکی PNG لە ناوەڕاستدا. دەبێت لەم هەبێت.

Lineدێڕی 7

Where the picture sits on Android: center, fill, top, bottom…

وێنەکە لە Androidـدا لە کوێ دادەنرێت: center، fill، top، bottom…

Quick checkپشکنینی خێراWhy is the colour written in quotes, "#42a5f5"?بۆچی ڕەنگەکە لەناو کەوانەدا نووسراوە، "#42a5f5"؟

Method 2: a native launch screen with flutter_native_splashڕێگای دووەم: شاشەی دەستپێکی ڕەسەن بە ⁦flutter_native_splash⁩

What the settings meanڕێکخستنەکان چی دەگەیەنن

These are the settings you will use most. Only color (or a background picture) is required.

ئەمانە ئەو ڕێکخستنانەن کە زۆرتر بەکاریان دەهێنیت. تەنها color (یان وێنەیەکی پاشبنەما) پێویستە.

The main settings of flutter_native_splash 2.4ڕێکخستنە سەرەکییەکانی ⁦flutter_native_splash 2.4⁩
SettingڕێکخستنWhat it doesچی دەکات
colorThe background colour, such as "#42a5f5".ڕەنگی پاشبنەما، وەک "#42a5f5".
imageA PNG in the centre. Make it for a 4× pixel density screen; the package makes the smaller sizes.PNGـێک لە ناوەڕاستدا. بۆ شاشەیەکی چڕیی 4× دروستی بکە؛ قەبارە بچووکترەکان دروست دەکات.
color_dark, image_darkThe same, for phones in dark mode.هەمان شت، بۆ مۆبایلەکان لە .
brandingA small picture near the bottom, for example the company's name.وێنەیەکی بچووک لە نزیک خوارەوە، بۆ نموونە ناوی کۆمپانیاکە.
android_gravityWhere the picture sits on Android: center, fill, top…وێنەکە لە Androidـدا لە کوێ دادەنرێت: center، fill، top…
ios_content_modeThe same for iOS: center, scaleAspectFit…هەمان شت بۆ iOS: center، scaleAspectFit…
fullscreentrue hides the status bar on Android while the launch screen shows (the iOS launch screen already hides it).true لە Androidـدا شریتی بارودۆخ دەشارێتەوە تا پیشان دەدرێت ( iOS خۆی دەیشارێتەوە).
android: falseDo not make a launch screen for this platform (also ios: and web:).بۆ ئەم دروست مەکە (هەروەها ios: و web:).

Because the native launch screen appears before Flutter runs, it cannot read your app's own settings. It follows the phone's light or dark mode, not a theme switch inside your app.

چونکە ڕەسەن پێش کارکردنی دەردەکەوێت، ناتوانێت ڕێکخستنەکانی خودی بخوێنێتەوە. شوێن دۆخی ڕووناک یان تاریکی مۆبایلەکە دەکەوێت، نەک دوگمەیەکی گۆڕینی لەناو .

Quick checkپشکنینی خێراYour app has its own dark-theme switch, and the user turned it on. The phone itself is in light mode. Which colour does the native launch screen use? دوگمەیەکی تایبەتی بۆ تاریک هەیە و هەڵیکردووە. خودی مۆبایلەکە لە دۆخی ڕووناکدایە. ڕەسەن کام ڕەنگ بەکار دەهێنێت؟

Method 2: a native launch screen with flutter_native_splashڕێگای دووەم: شاشەی دەستپێکی ڕەسەن بە ⁦flutter_native_splash⁩

Android 12 and newer⁦Android 12⁩ و نوێتر

Since Android 12, Android itself shows a launch screen for every app when the app starts from nothing (a cold start) or its screen has to be created again (a warm start): a single background colour with the app's icon in the middle, cut to a circle. It may also show an icon background. So on these phones the top-level settings are ignored, and flutter_native_splash reads an android_12: section instead:

لە ⁦Android 12⁩ـەوە، خودی Android بۆ هەموو پیشان دەدات کاتێک لە سفرەوە دەست پێ دەکات (دەستپێکردنی سارد) یان شاشەکەی دەبێت دووبارە دروست بکرێتەوە (دەستپێکردنی گەرم): یەک ڕەنگی پاشبنەما و لە ناوەڕاستدا، بە شێوەی بازنە بڕاوە. دەکرێت پاشبنەمایەکی پیشان بدات. بۆیە لەسەر ئەم مۆبایلانە ڕێکخستنەکانی ئاستی سەرەوە پشتگوێ دەخرێن و ⁦flutter_native_splash⁩ لە جیاتیان بەشی android_12: دەخوێنێتەوە:

An android_12 sectionبەشێکی ⁦android_12⁩pubspec.yamlYAML
flutter_native_splash:
  color: "#42a5f5"
  image: assets/splash.png

  android_12:
    color: "#42a5f5"
    image: assets/splash_icon.png
    icon_background_color: "#ffffff"
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 5

Indented under flutter_native_splash:: these settings are only for Android 12 and newer.

لە ژێر flutter_native_splash:ـدا بە بۆشایی سەرەتای دێڕەوە: ئەم ڕێکخستنانە تەنها بۆ ⁦Android 12⁩ و نوێترن.

Lineدێڕی 6

One plain colour. A background picture is not allowed here.

یەک ڕەنگی سادە. وێنەی پاشبنەما لێرە ڕێگەپێدراو نییە.

Lineدێڕی 7

The icon in the circle. Without it, Android uses the app's launcher icon.

لەناو بازنەکەدا. بەبێ ئەو، Android کردنەوەی بەکار دەهێنێت.

Lineدێڕی 8

An optional circle behind the icon, for more contrast.

بازنەیەکی هەڵبژاردەیی لە پشت ، بۆ جیاوازیی ڕەنگی زیاتر.

Two square icon canvases side by side. Left, 'without icon background': a square of 1152 by 1152 pixels with a dashed circle of 768 pixels in the middle; the logo must fit inside the circle, and everything outside it is cut away. Right, 'with icon_background_color': a square of 960 by 960 pixels with a filled circle of 640 pixels; the logo fits inside it. Under both: Android masks the icon to a circle; the background is one plain colour; no background picture.دوو ڕووبەری چوارگۆشەی ئایکۆن لە تەنیشت یەک. چەپ، «بەبێ پاشبنەمای ئایکۆن»: چوارگۆشەیەکی 1152 لە 1152 پیکسڵ بە بازنەیەکی پچڕپچڕی 768 پیکسڵ لە ناوەڕاستدا؛ لۆگۆکە دەبێت لەناو بازنەکەدا جێی ببێتەوە و هەرچی لە دەرەوەیەتی دەبڕدرێت. ڕاست، «بە icon_background_color»: چوارگۆشەیەکی 960 لە 960 پیکسڵ بە بازنەیەکی پڕی 640 پیکسڵ؛ لۆگۆکە لەناویدا جێی دەبێتەوە. لە ژێر هەردووکیاندا: Android ئایکۆنەکە بە بازنە دەبڕێت؛ پاشبنەما یەک ڕەنگی سادەیە؛ وێنەی پاشبنەما نییە.
Android 12 cuts the icon to a circle: keep your logo inside the safe circle.⁦Android 12⁩ بە بازنە دەبڕێت: لۆگۆکەت لەناو بازنە سەلامەتەکەدا بهێڵەرەوە.CêIT
  • Icon without an icon background: 1152×1152 px, with the logo inside a circle of 768 px.
  • Icon with icon_background_color: 960×960 px, with the logo inside a circle of 640 px.
  • The background is always one opaque colour; a background picture is not supported.
  • A branding picture is allowed (800×320 px), but Android's design guidance advises against it.
  • بەبێ پاشبنەمای : ⁦1152×1152 px⁩، لۆگۆکە لەناو بازنەیەکی ⁦768 px⁩ـدا.
  • بە icon_background_color: ⁦960×960 px⁩، لۆگۆکە لەناو بازنەیەکی ⁦640 px⁩ـدا.
  • پاشبنەما هەمیشە یەک ڕەنگی ناڕوونە؛ وێنەی پاشبنەما پشتگیری ناکرێت.
  • وێنەی branding ڕێگەپێدراوە ⁦(800×320 px)⁩، بەڵام ڕێنماییەکانی دیزاینی Android پێشنیاری ناکەن.
Quick checkپشکنینی خێراYou set a beautiful full-screen background picture at the top level of flutter_native_splash:, and an android_12: section with a colour and an icon. What does a phone with Android 14 show?وێنەیەکی جوانی پاشبنەمای پڕبەشاشەت لە ئاستی سەرەوەی flutter_native_splash:ـدا دانا، لەگەڵ بەشێکی android_12: بە ڕەنگێک و . مۆبایلێک بە ⁦Android 14⁩ چی پیشان دەدات؟

Method 2: a native launch screen with flutter_native_splashڕێگای دووەم: شاشەی دەستپێکی ڕەسەن بە ⁦flutter_native_splash⁩

Keep the launch screen while the app loadsشاشەی دەستپێکەکە بهێڵەرەوە تا ئەپەکە بار دەبێت

By default the native launch screen disappears as soon as Flutter draws its first frame. Some apps must do work before their first real screen makes sense: read saved settings, open a database, check whether the user is logged in. flutter_native_splash can keep its screen up until you say so:

بە شێوەی بنەڕەتی ڕەسەن هەر کە یەکەم دیمەن دەکێشێت لادەچێت. هەندێک پێش ئەوەی یەکەم شاشەی ڕاستەقینەیان مانای هەبێت دەبێت کارێک بکەن: خوێندنەوەی ڕێکخستنە پاشەکەوتکراوەکان، کردنەوەی ، پشکنینی ئەوەی چووەتە ژوورەوە یان نا. ⁦flutter_native_splash⁩ دەتوانێت شاشەکەی بهێڵێتەوە تا خۆت دەڵێیت:

preserve() and remove()⁦preserve()⁩ و ⁦remove()⁩DARTRuns on a phone (or an emulator)لەسەر مۆبایل کار دەکات
import 'package:flutter/material.dart';
import 'package:flutter_native_splash/flutter_native_splash.dart';

void main() {
  final widgetsBinding = WidgetsFlutterBinding.ensureInitialized();
  FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding);
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  void initState() {
    super.initState();
    _initialize();
  }

  Future<void> _initialize() async {
    // Real work goes here: read settings, open a database...
    await Future.delayed(const Duration(seconds: 1));
    FlutterNativeSplash.remove(); // now hide the native splash screen
  }

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: Scaffold(body: Center(child: Text('Ready'))),
    );
  }
}
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 5

Get the binding (Flutter's link to the engine) before runApp.

پێش runApp، binding وەربگرە (پەیوەندیی بە بزوێنەرەکەوە).

Lineدێڕی 6

preserve keeps the native launch screen after the first frame.

preserve ڕەسەن دوای یەکەم دیمەنیش دەهێڵێتەوە.

Lineدێڕی 24-28

Do the real loading here; this example only waits one second.

بارکردنی ڕاستەقینە لێرە بکە؛ ئەم نموونەیە تەنها یەک چرکە چاوەڕێ دەکات.

Lineدێڕی 27

remove hides the launch screen and shows your app.

remove دەشارێتەوە و پیشان دەدات.

Quick checkپشکنینی خێراWhen is the native launch screen removed in the code above?لە کۆدەکەی سەرەوەدا ڕەسەن کەی لادەبرێت؟

Method 1: a timed intro screen in Dartڕێگای یەکەم: شاشەیەکی ناساندنی کاتدار لە Dartـدا

The notes' first method is a normal Flutter screen: a stateful widget that shows a logo, waits a few seconds, and then puts the home screen in its place. It uses Timer() (or Future.delayed()) and one important method, initState().

ڕێگای یەکەمی تێبینییەکان شاشەیەکی ئاسایی Flutterـە: کە لۆگۆیەک پیشان دەدات، چەند چرکەیەک چاوەڕێ دەکات و پاشان شاشەی سەرەکی دەخاتە شوێنی خۆی. Timer() (یان Future.delayed()) و گرنگ، initState()، بەکار دەهێنێت.

How the timed intro worksشاشەی ناساندنی کاتدار چۆن کار دەکات
  1. initState() is called once, when the stateful widget is inserted into the widget tree.

    initState() یەک جار بانگ دەکرێت، کاتێک دەخرێتە ناو .

  2. It first calls super.initState(), then starts a timer for n seconds.

    سەرەتا بانگی super.initState() دەکات، پاشان کاتژمێرێک بۆ n چرکە دەست پێ دەکات.

  3. When the n seconds are over, the timer calls a function.

    کاتێک n چرکەکە تەواو دەبێت، کاتژمێرەکە بانگی دەکات.

  4. That function replaces the current screen with a new one, for example HomePage().

    ئەو شاشەی ئێستا بە شاشەیەکی نوێ دەگۆڕێت، بۆ نموونە HomePage().

This is the code from the notes. Read it first; the next screen shows a safe, complete version.

ئەمە کۆدەکەی تێبینییەکانە. سەرەتا بیخوێنەرەوە؛ شاشەی داهاتوو وەشانێکی سەلامەت و تەواو پیشان دەدات.

The notes' code (not complete)کۆدەکەی تێبینییەکان (تەواو نییە)DART
@override
void initState() {
  super.initState();
  startTimer();
}
startTimer() async {
  var duration = Duration(seconds: 4);
  return Timer(duration, route);
}
route(){
  Navigator.pushReplacement(context,
    MaterialPageRoute(builder: (context)=> HomePage()));
}
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 1-5

initState runs once. It calls super.initState() first, then starts the timer.

initState یەک جار جێبەجێ دەبێت. سەرەتا بانگی super.initState() دەکات، پاشان کاتژمێرەکە دەست پێ دەکات.

Lineدێڕی 6-9

Timer(duration, route) calls route once, after 4 seconds.

Timer(duration, route) یەک جار، دوای 4 چرکە، بانگی route دەکات.

Lineدێڕی 10-13

pushReplacement shows HomePage and removes the intro screen.

pushReplacement شاشەی HomePage پیشان دەدات و شاشەی ناساندنەکە لادەبات.

Quick checkپشکنینی خێراIn the notes' code, when does route run?لە کۆدەکەی تێبینییەکاندا، route کەی جێبەجێ دەبێت؟

4. Explaining SplashScreen (LaunchScreen) in Flutter (Central Kurdish)Aland Kawa Ali · Kurdish (Sorani)کوردی (سۆرانی) · 384 viewsبینین · 4 likesلایک

In Central Kurdish, by CêIT's author: a timed intro screen in Dart: a 5-second Timer in initState, then Navigator.pushReplacement to the home screen.

بە کوردیی ناوەندی، لەلایەن نووسەری CêITـەوە: کاتدار بە Dart — 5 چرکەیی لە initStateـدا، پاشان ⁦Navigator.pushReplacement⁩ بۆ شاشەی سەرەکی.

Whole video (8:25): Method 1 of this lesson, a StatefulWidget whose initState starts a Timer and then replaces the splash screen with the home screen.

هەموو ڤیدیۆکە ⁦(8:25)⁩: ڕێگەی 1ی ئەم وانەیە — کە initStateـەکەی دەستپێدەکات و پاشان بە شاشەی سەرەکی دەگۆڕێت.

Method 1: a timed intro screen in Dartڕێگای یەکەم: شاشەیەکی ناساندنی کاتدار لە Dartـدا

A safe, complete intro screenشاشەیەکی ناساندنی سەلامەت و تەواو

Here is the same idea as a complete app. It keeps the timer in a field, so it can stop it, and it checks that the screen still exists before it navigates:

ئەمە هەمان بیرۆکەیە وەک تەواو. کاتژمێرەکە لە هەڵدەگرێت بۆ ئەوەی بتوانێت بیوەستێنێت و پێش گواستنەوە دڵنیا دەبێتەوە کە شاشەکە هێشتا ماوە:

A timed intro screenشاشەیەکی ناساندنی کاتدارDARTRuns on a phone (or an emulator)لەسەر مۆبایل کار دەکات
import 'dart:async';

import 'package:flutter/material.dart';

void main() => runApp(const MaterialApp(home: SplashPage()));

class SplashPage extends StatefulWidget {
  const SplashPage({super.key});

  @override
  State<SplashPage> createState() => _SplashPageState();
}

class _SplashPageState extends State<SplashPage> {
  Timer? _timer;

  @override
  void initState() {
    super.initState();
    _timer = Timer(const Duration(seconds: 3), _goHome);
  }

  void _goHome() {
    if (!mounted) return; // the page may already be gone
    Navigator.pushReplacement(
      context,
      MaterialPageRoute(builder: (context) => const HomePage()),
    );
  }

  @override
  void dispose() {
    _timer?.cancel(); // stop the timer if the page closes early
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      backgroundColor: Colors.teal,
      body: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Icon(Icons.menu_book, size: 96, color: Colors.white),
            SizedBox(height: 16),
            Text(
              'Class Notes',
              style: TextStyle(fontSize: 28, color: Colors.white),
            ),
            SizedBox(height: 32),
            CircularProgressIndicator(color: Colors.white),
          ],
        ),
      ),
    );
  }
}

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Class Notes')),
      body: const Center(child: Text('Welcome!')),
    );
  }
}
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 1

Timer lives in dart:async; the notes forgot this import.

Timer لە dart:asyncـدایە؛ تێبینییەکان ئەم importـەیان لەبیر چووە.

Lineدێڕی 15

Keep the timer in a field, so dispose can cancel it.

کاتژمێرەکە لە هەڵبگرە، بۆ ئەوەی dispose بتوانێت هەڵیبوەشێنێتەوە.

Lineدێڕی 18-21

super.initState() first, then start a timer that calls _goHome once after 3 seconds.

سەرەتا super.initState()، پاشان کاتژمێرێک دەست پێ بکە کە دوای 3 چرکە یەک جار بانگی _goHome دەکات.

Lineدێڕی 24

If the page was closed meanwhile, context must not be used: stop here.

ئەگەر لەم ماوەیەدا لاپەڕەکە داخرابێت، نابێت context بەکار بهێنرێت: لێرە بوەستە.

Lineدێڕی 25-28

Replace this screen with the home page.

ئەم شاشەیە بە شاشەی سەرەکی بگۆڕە.

Lineدێڕی 31-35

Cancel the timer, then super.dispose() last.

کاتژمێرەکە هەڵبوەشێنەرەوە، پاشان لە کۆتاییدا super.dispose().

canPop = false in the test means there is no screen under the home page: the intro screen is really gone. The lifecycle methods initState, dispose and the mounted check are explained in the lifecycle of a State object.

canPop = false لە تاقیکردنەوەکەدا واتە هیچ شاشەیەک لە ژێر شاشەی سەرەکییەوە نییە: شاشەی ناساندنەکە بەڕاستی ڕۆیشتووە. initState، dispose و پشکنینی mounted لە سووڕی ژیانی ئۆبجێکتی دۆخ ڕوون کراونەتەوە.

Quick checkپشکنینی خێراWhy does the safe version call _timer?.cancel() in dispose?بۆچی وەشانە سەلامەتەکە لە disposeـدا بانگی _timer?.cancel() دەکات؟

Method 1: a timed intro screen in Dartڕێگای یەکەم: شاشەیەکی ناساندنی کاتدار لە Dartـدا

Why pushReplacement, not push?بۆچی pushReplacement، نەک push؟

Flutter keeps the screens you open in a stack, one on top of the other. Navigator.push puts a new screen on top and keeps the old one under it. Navigator.pushReplacement puts the new screen on top and removes the old one.

ئەو شاشانەی دەیانکەیتەوە لە هەڵدەگرێت، یەک لەسەر یەک. Navigator.push شاشەیەکی نوێ دەخاتە سەرەوە و کۆنەکە لە ژێریدا دەهێڵێتەوە. Navigator.pushReplacement شاشە نوێیەکە دەخاتە سەرەوە و کۆنەکە لادەبات.

With push, the intro screen would stay under the home page, and the Back button would take the user back to the logo. With pushReplacement it is gone, so Back from the home page leaves the app, as users expect. The stack itself is taught in Navigation: moving between screens.

بە push، شاشەی ناساندنەکە لە ژێر شاشەی سەرەکییەوە دەمایەوە و Back دەگەڕاندەوە بۆ لۆگۆکە. بە pushReplacement نامێنێت، بۆیە Back لە شاشەی سەرەکییەوە دادەخات، وەک چاوەڕێی دەکەن. خودی لە ڕێنیشاندان: جووڵان لە نێوان شاشەکاندا دەخوێنرێت.

Quick checkپشکنینی خێراAn intro screen opens the home page with Navigator.push. What happens when the user presses Back on the home page?شاشەیەکی ناساندن شاشەی سەرەکی بە Navigator.push دەکاتەوە. کاتێک لە شاشەی سەرەکیدا Back دەکات چی ڕوو دەدات؟

Method 1: a timed intro screen in Dartڕێگای یەکەم: شاشەیەکی ناساندنی کاتدار لە Dartـدا

The other way: Future.delayedڕێگاکەی تر: ⁦Future.delayed⁩

The notes also mention the delayed() function. Future.delayed(duration, callback) waits, then calls the callback, much like a one-time Timer:

تێبینییەکان باسی delayed()ـیش دەکەن. Future.delayed(duration, callback) چاوەڕێ دەکات، پاشان بانگی دەکات، زۆر وەک Timerـێکی یەکجاری:

The same intro with Future.delayedهەمان ناساندن بە ⁦Future.delayed⁩DARTRuns on a phone (or an emulator)لەسەر مۆبایل کار دەکات
import 'package:flutter/material.dart';

class SplashPage extends StatefulWidget {
  const SplashPage({super.key});

  @override
  State<SplashPage> createState() => _SplashPageState();
}

class _SplashPageState extends State<SplashPage> {
  @override
  void initState() {
    super.initState();
    Future.delayed(const Duration(seconds: 3), () {
      if (!mounted) return; // a delayed Future cannot be cancelled
      Navigator.pushReplacement(
        context,
        MaterialPageRoute(builder: (context) => const HomePage()),
      );
    });
  }

  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      body: Center(child: FlutterLogo(size: 120)),
    );
  }
}

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return const Scaffold(body: Center(child: Text('Home')));
  }
}
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 14-20

Wait 3 seconds, then replace the screen.

3 چرکە چاوەڕێ بکە، پاشان شاشەکە بگۆڕە.

Lineدێڕی 15

A Future cannot be cancelled, so the mounted check is the only protection here.

هەڵناوەشێنرێتەوە، بۆیە پشکنینی mounted لێرەدا تاکە پاراستنە.

Both work. Prefer the Timer when the user can leave early, for example with a Skip button, because a timer can be cancelled and a delayed Future cannot. Future and await are taught in Futures and async.

هەردووکیان کار دەکەن. کاتێک دەتوانێت زوو بڕوات، بۆ نموونە بە Skip، Timer باشترە، چونکە کاتژمێر هەڵدەوەشێنرێتەوە بەڵام Futureـی دواخراو نا. و await لە Futures و async دەخوێنرێن.

Quick checkپشکنینی خێراWhich one can you stop before it fires?کامیان دەتوانیت پێش لێدانی ڕایبگریت؟

A good splash screenشاشەیەکی دەستپێکی باش

  • Keep it short. Android's guide recommends at most one second even for an animated launch icon. Never add a timer only to show a logo longer.
  • Match the first screen. Use the same background colour as your first Flutter screen, so the change from native to Flutter does not flash.
  • Load real things, not fake waits. If the app truly needs to load data, use preserve/remove, or show the first screen at once with a progress indicator.
  • Little or no text. A logo needs no translation; text on a launch screen cannot follow the user's language.
  • Think of dark mode. Give color_dark (and image_dark if needed).
  • کورتی بکەرەوە. ڕێنماییەکانی Android تەنانەت بۆ ئامۆژگاری دەکەن لە یەک چرکە زیاتر نەبێت. هەرگیز کاتژمێر تەنها بۆ پیشاندانی درێژتری لۆگۆیەک زیاد مەکە.
  • لەگەڵ یەکەم شاشەدا بیگونجێنە. هەمان ڕەنگی پاشبنەمای یەکەم شاشەی Flutterـەکەت بەکار بهێنە، بۆ ئەوەی گۆڕان لە ڕەسەنەوە بۆ Flutter نەدرەوشێتەوە.
  • شتی ڕاستەقینە بار بکە، نەک چاوەڕوانیی ساختە. ئەگەر بەڕاستی پێویستی بە بارکردنی هەیە، preserve/remove بەکار بهێنە، یان یەکسەر یەکەم شاشە لەگەڵ نیشاندەرێکی پێشکەوتن پیشان بدە.
  • دەقی کەم یان هیچ. لۆگۆ پێویستی بە وەرگێڕان نییە؛ دەق لەسەر ناتوانێت شوێن زمانی بکەوێت.
  • بیر لە بکەرەوە. color_dark (و ئەگەر پێویست بوو image_dark) دابنێ.
Quick checkپشکنینی خێراYour app is ready in 0.4 seconds, but a Timer keeps a logo on screen for 5 seconds. What is the problem? لە ⁦0.4⁩ چرکەدا ئامادەیە، بەڵام Timerـێک لۆگۆیەک بۆ 5 چرکە لەسەر شاشە دەهێڵێتەوە. کێشەکە چییە؟

Common mistakesهەڵە باوەکان

MistakeهەڵەWhat happensچی ڕوو دەداتFixچاککردن
Running flutter pub run flutter_native_splash:createجێبەجێکردنی flutter pub run flutter_native_splash:createA deprecation warning; old guides use itئاگادارییەکی بەسەرچوون؛ ڕێنمایی کۆنەکان بەکاری دەهێننdart run flutter_native_splash:createdart run flutter_native_splash:create
Changing the settings and pressing hot reloadگۆڕینی ڕێکخستنەکان و The old launch screen stays کۆن دەمێنێتەوەRun the create command again, then stop and restart the appدووبارە فەرمانی create جێبەجێ بکە، پاشان ڕابگرە و دەستی پێ بکەرەوە
A background picture for Android 12+وێنەی پاشبنەما بۆ ⁦Android 12+⁩Android shows only a colour and the iconAndroid تەنها ڕەنگێک و پیشان دەداتUse the android_12: section with a colour and an iconبەشی android_12: بە ڕەنگێک و بەکار بهێنە
Checking the launch screen only by running the app from Android Studio on Android 12 (API 31)پشکنینی تەنها بە کارپێکردنی لە ⁦Android Studio⁩ـەوە لەسەر ⁦Android 12 (API 31)⁩The launch screen may not appear at allلەوانەیە هەر دەرنەکەوێتClose the app and open it from its icon on the phone دابخە و لە لەسەر مۆبایلەکە بیکەرەوە
Timer without import 'dart:async';Timer بەبێ import 'dart:async';Compile error: Timer is not defined کۆمپایل: Timer پێناسە نەکراوەAdd the importimportـەکە زیاد بکە
push instead of pushReplacementpush لە جیاتی pushReplacementBack returns to the intro screenBack دەگەڕێتەوە بۆ شاشەی ناساندنەکەNavigator.pushReplacementNavigator.pushReplacement
Not cancelling the timer; no mounted checkهەڵنەوەشاندنەوەی کاتژمێرەکە؛ پشکنینی mounted نییەThe timer may fire after the screen is gone and use a dead contextلەوانەیە کاتژمێرەکە دوای ڕۆیشتنی شاشەکە لێ بدات و contextـێکی مردوو بەکار بهێنێت_timer?.cancel() in dispose; if (!mounted) return;_timer?.cancel() لە disposeـدا؛ if (!mounted) return;
Importing flutter_native_splash in code while it is a dev dependencyimport کردنی ⁦flutter_native_splash⁩ لە کۆددا لە کاتێکدا لە ژێر dev_dependenciesـدایەA lint warning, and the package may be missing from the released appئاگادارییەکی lint و لەوانەیە لە بڵاوکراوەکەدا نەبێتMove it to dependenciesبیگوازەرەوە بۆ dependencies

Exercisesڕاهێنانەکان

Exerciseڕاهێنان1. Order the stages١. قۆناغەکان ڕیز بکە

Put these in the order a user sees them: the home screen; the native launch screen; the tap on the icon; a Dart intro screen with an animated logo.

ئەمانە بەو ڕیزەیە دابنێ کە دەیانبینێت: شاشەی سەرەکی؛ ڕەسەن؛ دەستلێدان لە ؛ شاشەیەکی ناساندنی بە لۆگۆیەکی جووڵاوەوە.

Show answerوەڵامەکە پیشان بدە

1. The tap on the icon. 2. The native launch screen (until Flutter's first frame). 3. The Dart intro screen. 4. The home screen.

١. دەستلێدان لە . ٢. ڕەسەن (تا یەکەم دیمەنی Flutter). ٣. شاشەی ناساندنی . ٤. شاشەی سەرەکی.

Exerciseڕاهێنان2. Write the settings٢. ڕێکخستنەکان بنووسە

Your logo is assets/logo.png. Write the flutter_native_splash section for a white background (#ffffff) in light mode and a black one (#000000) in dark mode, with the logo centred, and the same colours on Android 12+. Then write the command that generates the files.

لۆگۆکەت assets/logo.pngـە. بەشی flutter_native_splash بنووسە بۆ پاشبنەمایەکی سپی (#ffffff) لە دۆخی ڕووناکدا و ڕەش (#000000) لە ، لۆگۆکە لە ناوەڕاستدا و هەمان ڕەنگەکان لەسەر ⁦Android 12+⁩. پاشان ئەو فەرمانە بنووسە کە دروست دەکات.

Hintئاماژە

Remember that Android 12+ reads only its own section.

لەبیرت بێت ⁦Android 12+⁩ تەنها بەشی خۆی دەخوێنێتەوە.

Show answerوەڵامەکە پیشان بدە
pubspec.yamlYAML
flutter_native_splash:
  color: "#ffffff"
  color_dark: "#000000"
  image: assets/logo.png
  android_gravity: center
  ios_content_mode: center

  android_12:
    color: "#ffffff"
    color_dark: "#000000"
    image: assets/logo.png
BASHType in a terminalلە تێرمیناڵدا بینووسە
$ dart run flutter_native_splash:create
Exerciseڕاهێنان3. Fix the notes' timer code٣. کۆدی کاتژمێرەکەی تێبینییەکان چاک بکە

List four problems in the notes' initState / startTimer / route code, and say how to fix each.

چوار کێشە لە کۆدی initState / startTimer / routeـی تێبینییەکاندا بنووسە و بڵێ هەر یەکەیان چۆن چاک دەکرێت.

Show answerوەڵامەکە پیشان بدە
  • Timer needs import 'dart:async';.
  • startTimer is async with no return type and awaits nothing: make it void _startTimer() or create the timer straight in initState.
  • The timer is not kept, so it cannot be cancelled: store it in Timer? _timer and call _timer?.cancel() in dispose.
  • route uses context after waiting: start it with if (!mounted) return;.
  • Also: HomePage() can be const HomePage(), and private names (_route) are clearer.
  • Timer پێویستی بە import 'dart:async'; هەیە.
  • startTimer بە asyncـە و جۆری نییە و چاوەڕێی هیچ ناکات: بیکە void _startTimer() یان کاتژمێرەکە ڕاستەوخۆ لە initStateـدا دروست بکە.
  • کاتژمێرەکە هەڵنەگیراوە، بۆیە هەڵناوەشێنرێتەوە: لە Timer? _timerـدا هەڵیبگرە و لە disposeـدا بانگی _timer?.cancel() بکە.
  • route دوای چاوەڕوانی context بەکار دەهێنێت: بە if (!mounted) return; دەستی پێ بکە.
  • هەروەها: HomePage() دەکرێت const HomePage() بێت و ناوی تایبەت (_route) ڕوونترن.
Exerciseڕاهێنان4. A Skip button٤. دوگمەیەکی Skip

Change the timed intro screen so it waits 5 seconds, but shows a Skip button in the top corner that goes to the home page at once. Make sure the timer cannot open the home page a second time.

شاشەی ناساندنی کاتدار بگۆڕە بۆ ئەوەی 5 چرکە چاوەڕێ بکات، بەڵام Skip لە گۆشەی سەرەوەدا پیشان بدات کە یەکسەر دەچێت بۆ شاشەی سەرەکی. دڵنیا بە کاتژمێرەکە ناتوانێت جارێکی تر شاشەی سەرەکی بکاتەوە.

Hintئاماژە

Let the timer and the button call the same method.

با کاتژمێرەکە و بانگی هەمان بکەن.

Show answerوەڵامەکە پیشان بدە
DARTRuns on a phone (or an emulator)لەسەر مۆبایل کار دەکات
import 'dart:async';

import 'package:flutter/material.dart';

class IntroPage extends StatefulWidget {
  const IntroPage({super.key});

  @override
  State<IntroPage> createState() => _IntroPageState();
}

class _IntroPageState extends State<IntroPage> {
  Timer? _timer;

  @override
  void initState() {
    super.initState();
    _timer = Timer(const Duration(seconds: 5), _goHome);
  }

  void _goHome() {
    _timer?.cancel(); // needed when the user taps Skip early
    if (!mounted) return;
    Navigator.pushReplacement(
      context,
      MaterialPageRoute(builder: (context) => const HomePage()),
    );
  }

  @override
  void dispose() {
    _timer?.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Stack(
          children: [
            const Center(child: FlutterLogo(size: 120)),
            Align(
              alignment: AlignmentDirectional.topEnd,
              child: TextButton(
                onPressed: _goHome,
                child: const Text('Skip'),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return const Scaffold(body: Center(child: Text('Home')));
  }
}
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 21-28

Both the timer and the button call _goHome. It cancels the timer first, so a tap on Skip stops the later call.

هەم کاتژمێرەکە و هەم بانگی _goHome دەکەن. سەرەتا کاتژمێرەکە هەڵدەوەشێنێتەوە، بۆیە دەستلێدان لە Skip بانگکردنە دواترەکە ڕادەگرێت.

Lineدێڕی 43-49

AlignmentDirectional.topEnd puts the button in the top-right corner, or top-left in a right-to-left language such as Kurdish.

AlignmentDirectional.topEnd لە گۆشەی سەرەوەی ڕاست دادەنێت، یان سەرەوەی چەپ لە زمانێکی وەک کوردیدا.

Exerciseڕاهێنان5. Native or Dart?٥. ڕەسەن یان Dart؟

For each wish, say whether it needs the native launch screen, a Dart intro screen, or preserve/remove: (a) a coloured screen must appear the moment the icon is tapped; (b) the logo should spin for one second; (c) the launch screen must stay until saved settings are loaded.

بۆ هەر ئارەزوویەک بڵێ پێویستی بە ڕەسەن، شاشەیەکی ناساندنی یان preserve/remove هەیە: (أ) شاشەیەکی ڕەنگاوڕەنگ دەبێت هەر کە دەست لە درا دەربکەوێت؛ (ب) لۆگۆکە بۆ یەک چرکە بسووڕێتەوە؛ (ج) دەبێت بمێنێتەوە تا ڕێکخستنە پاشەکەوتکراوەکان بار دەبن.

Show answerوەڵامەکە پیشان بدە
  • (a) The native launch screen: only it can appear before Flutter runs.
  • (b) A Dart intro screen: animation needs Flutter widgets.
  • (c) FlutterNativeSplash.preserve() in main, remove() after loading.
  • (أ) ڕەسەن: تەنها ئەو دەتوانێت پێش کارکردنی دەربکەوێت.
  • (ب) شاشەیەکی ناساندنی : پێویستی بە هەیە.
  • (ج) FlutterNativeSplash.preserve() لە mainـدا، remove() دوای بارکردن.
Quick checkپشکنینی خێراWhat does Navigator.pushReplacement do with the current screen?Navigator.pushReplacement چی بە شاشەی ئێستا دەکات؟

Summaryپوختە

  • A splash (launch) screen is the first screen of an app: usually a logo or name on a plain background, shown while the app starts.
  • The native launch screen is drawn by Android/iOS until Flutter's first frame. flutter_native_splash 2.4 makes it: settings in pubspec.yaml, then dart run flutter_native_splash:create.
  • Android 12+ uses only its own android_12: settings: one colour and an icon in a circle.
  • preserve() and remove() keep the native screen while the app loads real data.
  • A Dart intro screen is optional: a stateful widget that starts a Timer in initState, cancels it in dispose, checks mounted, and leaves with pushReplacement.
  • Keep splash screens short: they cover start-up time, they are not a place to make users wait.
  • یەکەم شاشەی : زۆرجار لۆگۆ یان ناوێک لەسەر پاشبنەمایەکی سادە، کە لە کاتی دەستپێکردنی پیشان دەدرێت.
  • ڕەسەن ⁦Android/iOS⁩ دەیکێشن تا یەکەم دیمەنی ⁦Flutter. flutter_native_splash 2.4⁩ دروستی دەکات: ڕێکخستنەکان لە pubspec.yamlـدا، پاشان dart run flutter_native_splash:create.
  • ⁦Android 12+⁩ تەنها ڕێکخستنەکانی android_12:ـی خۆی بەکار دەهێنێت: یەک ڕەنگ و لەناو بازنەیەکدا.
  • preserve() و remove() شاشە ڕەسەنەکە دەهێڵنەوە تا ڕاستەقینە بار دەکات.
  • شاشەی ناساندنی هەڵبژاردەییە: کە لە initStateـدا Timerـێک دەست پێ دەکات، لە disposeـدا هەڵیدەوەشێنێتەوە، mounted دەپشکنێت و بە pushReplacement دەڕوات.
  • کورت بهێڵەرەوە: کاتی دەستپێکردن دادەپۆشن، شوێنی چاوەڕێ پێکردنی نین.
Review questionsپرسیارەکانی پێداچوونەوە
Which method of the notes makes the screen that appears before Flutter runs?کام ڕێگای تێبینییەکان ئەو شاشەیە دروست دەکات کە پێش کارکردنی Flutter دەردەکەوێت؟

Method 2, the flutter_native_splash package. Method 1 (the Timer) is a Flutter screen, so it can only appear after Flutter has started.

ڕێگای دووەم، ⁦flutter_native_splash⁩. ڕێگای یەکەم ⁦(Timer)⁩ شاشەیەکی Flutterـە، بۆیە تەنها دوای دەستپێکردنی Flutter دەتوانێت دەربکەوێت.

Why must the timer be cancelled in dispose?بۆچی دەبێت کاتژمێرەکە لە disposeـدا هەڵبوەشێنرێتەوە؟

If the screen closes before the time is up, a waiting timer would still fire and try to navigate with a context that no longer exists.

ئەگەر شاشەکە پێش تەواوبوونی کاتەکە دابخرێت، کاتژمێرێکی چاوەڕوان هێشتا لێ دەدات و هەوڵ دەدات بە contextـێک بگوازێتەوە کە چیتر بوونی نییە.

Where do the android_12 settings go?ڕێکخستنەکانی ⁦android_12⁩ کوێ دەچن؟

Indented inside the flutter_native_splash: section of pubspec.yaml, under the key android_12:.

لەناو بەشی flutter_native_splash:ـی pubspec.yamlـدا بە بۆشایی سەرەتای دێڕەوە، لە ژێر کلیلی android_12:ـدا.

Lesson complete!وانەکە تەواو بوو!

Well done. Review the key terms, then go on to the next lesson.دەستخۆش. سەیرێکی زاراوە سەرەکییەکان بکەرەوە، پاشان بڕۆ بۆ وانەی داهاتوو.

Key termsزاراوە سەرەکییەکان

Next lessonوانەی داهاتوو

Navigation: Moving Between Screensڕێنیشاندان: جووڵان لە نێوان شاشەکاندا

References and further readingسەرچاوەکان و خوێندنەوەی زیاتر

This lecture is a first edition. The Kurdish text and terminology are waiting for review by Kurdish IT teachers.ئەم وانەیە چاپی یەکەمە. دەقە کوردییەکە و زاراوەکانی چاوەڕێی پێداچوونەوەی مامۆستایانی کوردی بواری IT ن.