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

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

Routes and the Navigator's stack; going forward with Navigator.push and MaterialPageRoute and back with Navigator.pop; a complete two-screen app; sending data through a constructor and getting a value back with await push and pop; replacing and clearing routes; and named routes and go_router as next steps.

و Navigator؛ چوونە پێشەوە بە ⁦Navigator.push⁩ و MaterialPageRoute و گەڕانەوە بە ⁦Navigator.pop⁩؛ تەواوی دوو شاشەیی؛ ناردنی لە ڕێگەی و وەرگرتنەوەی نرخێک بە ⁦await push⁩ و pop؛ گۆڕین و پاککردنەوەی ؛ و ناودار و ⁦go_router⁩ وەک هەنگاوی داهاتوو.

18 min read16 خولەک خوێندنەوە · 15 stepsهەنگاو

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

  • Explain routes and how the Navigator keeps them in a stack.
  • Move between two screens with Navigator.push, MaterialPageRoute and Navigator.pop.
  • Send data to a screen through its constructor, and get a result back with await push and pop.
  • Choose pushReplacement or pushAndRemoveUntil when a screen must not come back, and know when to reach for go_router.
  • ڕوون بکەیتەوە و بڵێیت Navigator چۆن لە هەڵیاندەگرێت.
  • بە ⁦Navigator.push⁩، MaterialPageRoute و ⁦Navigator.pop⁩ لە نێوان دوو شاشەدا بجووڵێیت.
  • لە ڕێگەی بنێریت بۆ شاشەیەک و ئەنجامێک بە ⁦await push⁩ و pop وەربگریتەوە.
  • کاتێک نابێت شاشەیەک بگەڕێتەوە pushReplacement یان pushAndRemoveUntil هەڵبژێریت و بزانیت کەی پێویستت بە ⁦go_router⁩ دەبێت.

Apps have many screensئەپەکان چەندین شاشەیان هەیە

Almost every app has more than one screen. A shop app shows a list of products; you tap one and a details screen opens; you press Back and you are on the list again. Navigation and routing let the user move between the pages of an app in this way.

نزیکەی هەموو زیاتر لە یەک شاشەی هەیە. فرۆشگا لیستی کاڵاکان پیشان دەدات؛ دەست لە یەکێکیان دەدەیت و شاشەی وردەکارییەکان دەکرێتەوە؛ Back دەکەیت و دووبارە لەسەر لیستەکەیت. ڕێگە بە دەدات بەم شێوەیە لە نێوان لاپەڕەکانی بجووڵێت.

Definitionپێناسە

Moving between the screens of an app and keeping track of where the user has been, so that Back returns to the previous screen. In Flutter the Navigator keeps the screens () in a .

جووڵان لە نێوان شاشەکانی ئەپێکدا و هەڵگرتنی ئەوەی بەکارهێنەر بە کوێدا ڕۆیشتووە، بۆ ئەوەی گەڕانەوە بیباتەوە بۆ شاشەی پێشوو. لە Navigator شاشەکان () لە هەڵدەگرێت.

In Flutter, the screens or pages of an app are called routes, and a route is just a widget. Each screen you design, such as a list screen or a details screen, is an ordinary widget class.

لە ، شاشە یان لاپەڕەکانی پێیان دەوترێت و تەنها . هەر شاشەیەک کە دیزاینی دەکەیت، وەک شاشەی لیست یان شاشەی وردەکاری، ئاسایی .

Quick checkپشکنینی خێراIn Flutter, what is a route?لە ، چییە؟

The Navigator keeps routes in a stackNavigator ڕێگەکان لە ستاکێکدا هەڵدەگرێت

Creating routes and MaterialPageRouteدروستکردنی ڕێگەکان و MaterialPageRoute

A route is written as a class, using object-oriented ideas: each route is a separate class with its own contents and UI, for example class FirstRoute extends StatelessWidget. To show it, you wrap it in a route object. The usual one is MaterialPageRoute: a full-screen page with the platform's own animation: on iOS it slides in from the right; on Android it slides in from the side while fading in, and on Android 14 and newer it follows the user's finger during the Back swipe (predictive back).

وەک دەنووسرێت، بە بیرۆکەکانی : هەر جیایە بە ناوەڕۆک و شێوەی خۆیەوە، بۆ نموونە class FirstRoute extends StatelessWidget. بۆ پیشاندانی، دەیخەیتە ناو . باوترینیان MaterialPageRouteـە: لاپەڕەیەکی پڕبەشاشە بە تایبەتی : لە iOSـدا لە لای ڕاستەوە دێتە ناوەوە؛ لە Androidـدا لە لاوە دێتە ناوەوە و هێدی هێدی ڕوون دەبێتەوە و لە ⁦Android 14⁩ و نوێتردا لە کاتی ڕاکێشانی پەنجە بۆ Back شوێن پەنجەی دەکەوێت ⁦(predictive back)⁩.

A route made from a widgetڕێگەیەک کە لە ویجێتێک دروست کراوەDART
MaterialPageRoute(builder: (context) => const SecondRoute())
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 1

builder is a function that returns the screen's widget. Flutter calls it when the route is built.

builder کە شاشەکە دەگەڕێنێتەوە. کاتێک دروست دەکرێت بانگی دەکات.

Quick checkپشکنینی خێراWhich part is the route in Navigator.push(context, MaterialPageRoute(builder: (context) => const SecondRoute()))?لە Navigator.push(context, MaterialPageRoute(builder: (context) => const SecondRoute()))ـدا کام بەش ؟

Going to a new screen: Navigator.pushچوون بۆ شاشەیەکی نوێ: ⁦Navigator.push⁩

To display the second route, call Navigator.push(). It takes the context (so it can find the Navigator above this widget) and the route to put on top:

بۆ پیشاندانی دووەم، بانگی Navigator.push() بکە. context وەردەگرێت (بۆ ئەوەی Navigatorـی سەرووی ئەم بدۆزێتەوە) و ئەو دەخرێتە سەرەوە:

Push the second routeڕێگەی دووەم push بکەDART
// Within the HomeRoute widget
onPressed: () {
  Navigator.push(
    context,
    MaterialPageRoute(builder: (context) => const SecondRoute()),
  );
},
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 2

The button's callback: it runs when the button is tapped.

: کاتێک دەست لە دەدرێت جێبەجێ دەبێت.

Lineدێڕی 4

context is this widget's place in the tree. The Navigator is found above it.

context شوێنی ئەم لە دارەکەدا. Navigator لە سەرووی ئەوەوە دەدۆزرێتەوە.

Lineدێڕی 5

A new route that builds SecondRoute.

نوێ کە SecondRoute دروست دەکات.

context is the widget's BuildContext, explained in build and context. Using Navigator.of(context).push(route) is the same call written another way.

context BuildContextـی کە لە build و context ڕوون کراوەتەوە. Navigator.of(context).push(route) هەمان بانگکردنە بە شێوەیەکی تر نووسراوە.

Quick checkپشکنینی خێراWhat does Navigator.push do to the stack?Navigator.push چی بە دەکات؟

بنەماکانی فلاتەر: فێرکاری بۆ ئاستی دەستپێک (1.5 کاتژمێر) | Flutter Fundamentals: Beginner (1.5-Hour)Flutter Kurd Code · Kurdish (Sorani)کوردی (سۆرانی) · 5.3K viewsبینین · 183 likesلایک · Partبەشی 54:04–56:52 (ofلە 1:30:00)

A Kurdish beginner course: what Flutter is, making an Android emulator, creating and running a project in VS Code, Hello World and hot reload.

کۆرسێکی کوردی بۆ سەرەتاییەکان: چییە، دروستکردنی Android، دروستکردن و کارپێکردنی پرۆژەیەک لە ⁦VS Code⁩ـدا، ⁦Hello World⁩ و .

Watch 54:04–56:52 (Kurdish): a second screen in its own file and Navigator.push with MaterialPageRoute.

لە ⁦54:04⁩ تا ⁦56:52⁩ سەیر بکە (بە کوردی): شاشەیەکی دووەم لە خۆیدا و Navigator.push لەگەڵ MaterialPageRoute.

Going back: Navigator.popگەڕانەوە: ⁦Navigator.pop⁩

To go back, call Navigator.pop(). It removes the current (top) route, so the route under it, here the home route, is shown again:

بۆ گەڕانەوە، بانگی Navigator.pop() بکە. ئێستا (سەرەوە) لادەبات، بۆیە ئەو لە ژێریدایە، لێرەدا سەرەکی، دووبارە پیشان دەدرێتەوە:

Pop the current routeڕێگەی ئێستا pop بکەDART
// Within the SecondRoute widget
onPressed: () {
  Navigator.pop(context);
},

You often do not need to write this. When a route is pushed on top of another, the AppBar shows a back arrow by itself, and the Android Back button and the iOS swipe from the edge also pop the route.

زۆرجار پێویست ناکات ئەمە بنووسیت. کاتێک لەسەر یەکێکی تر push دەکرێت، AppBar خۆی تیرێکی گەڕانەوە پیشان دەدات و Backـی Android و ڕاکێشانی پەنجە لە لێوارەوە لە iOSـدا هەمان pop دەکەن.

Quick checkپشکنینی خێراWhere does the back arrow in the second screen's app bar come from?تیری گەڕانەوە لە شاشەی دووەمدا لە کوێوە دێت؟

A complete two-screen appئەپێکی تەواوی دوو شاشەیی

Steps to create navigationهەنگاوەکانی دروستکردنی ڕێنیشاندان
  1. Create two routes (screens): FirstRoute and SecondRoute.

    دوو (شاشە) دروست بکە: FirstRoute و SecondRoute.

  2. Go from the first route to the second with Navigator.push().

    بە Navigator.push() لە یەکەمەوە بچۆ بۆ دووەم.

  3. Come back to the first route with Navigator.pop().

    بە Navigator.pop() بگەڕێوە بۆ یەکەم.

Two routes with push and popدوو ڕێگە بە push و popDARTRuns on a phone (or an emulator)لەسەر مۆبایل کار دەکات
import 'package:flutter/material.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('First Screen')),
      body: Center(
        child: ElevatedButton(
          style: ElevatedButton.styleFrom(
            backgroundColor: Colors.orangeAccent,
          ),
          onPressed: () {
            // Navigate to the second route when tapped.
            Navigator.push(
              context,
              MaterialPageRoute(builder: (context) => const SecondRoute()),
            );
          },
          child: const Text('Click Here'),
        ),
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Second Screen')),
      body: Center(
        child: ElevatedButton(
          style: ElevatedButton.styleFrom(
            backgroundColor: Colors.red,
            foregroundColor: Colors.white,
          ),
          onPressed: () {
            // Navigate back to the first route when tapped.
            Navigator.pop(context);
          },
          child: const Text('Go Back'),
        ),
      ),
    );
  }
}
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 3

home: is the first route at the bottom of the stack.

home: یەکەم لە بنی .

Lineدێڕی 5-6

A route is an ordinary widget class with a const constructor.

ئاسایی بە constـەوە.

Lineدێڕی 13-16

ElevatedButton replaces the old RaisedButton; its colour goes in style.

ElevatedButton جێگەی RaisedButtonـی کۆن دەگرێتەوە؛ ڕەنگەکەی دەچێتە ناو style.

Lineدێڕی 19-22

push: put SecondRoute on top.

push: SecondRoute بخە سەرەوە.

Lineدێڕی 46

pop: remove SecondRoute; FirstRoute shows again.

pop: SecondRoute لاببە؛ FirstRoute دووبارە دەردەکەوێتەوە.

Two phone screens. Left: an app bar 'First Screen' and an orange button 'Click Here' in the middle. An arrow labelled Navigator.push goes to the right phone: an app bar with a back arrow and the title 'Second Screen', and a red button 'Go Back'. An arrow back to the left, labelled Navigator.pop, starts from the Go Back button and from the back arrow.دوو شاشەی مۆبایل. چەپ: شریتێکی ئەپ «First Screen» و دوگمەیەکی پرتەقاڵیی «Click Here» لە ناوەڕاستدا. تیرێک بە ناونیشانی Navigator.push دەچێت بۆ مۆبایلی ڕاست: شریتێکی ئەپ بە تیری گەڕانەوە و ناونیشانی «Second Screen» و دوگمەیەکی سووری «Go Back». تیرێکی گەڕانەوە بۆ چەپ، بە ناونیشانی Navigator.pop، لە دوگمەی Go Back و لە تیری گەڕانەوەوە دەست پێ دەکات.
The two-screen app: push goes forward, pop (the button or the back arrow) comes back. دوو شاشەیی: push دەچێتە پێشەوە، pop ( یان تیری گەڕانەوە) دەگەڕێتەوە.CêIT
Quick checkپشکنینی خێراIn the example, what happens when the user taps the back arrow in the app bar of the second screen?لە نموونەکەدا، کاتێک دەست لە تیری گەڕانەوەی شاشەی دووەم دەدات چی ڕوو دەدات؟

Sending data to the next screenناردنی دراوە بۆ شاشەی داهاتوو

Often the second screen needs data from the first: the product that was tapped, a name, a message. The notes explain the way: give the second screen a constructor that receives a key and then the data. The first screen passes the data when it creates the route:

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

The notes' code (two pictures)کۆدەکەی تێبینییەکان (دوو وێنە)DART
ElevatedButton(
  child: Text("Send Data"),
  onPressed:(){
    Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context)=> SecondScreen(getData: "Hello Students")));
  },
),

// in the second screen
String getData = '';
SecondScreen({Key? key, required this.getData}) : super(key: key);
. . .
body: Center(
  child: Text(getData),
),

The idea is right, but the field is written in an old and unsafe way. A widget is immutable: its fields must be final. Today it looks like this:

بیرۆکەکە ڕاستە، بەڵام بە شێوەیەکی کۆن و ناسەلامەت نووسراوە. : دەبێت final بن. ئەمڕۆ بەم شێوەیە دەنووسرێت:

Passing a message through the constructorناردنی نامەیەک لە ڕێگەی دروستکەرەوەDARTRuns on a phone (or an emulator)لەسەر مۆبایل کار دەکات
import 'package:flutter/material.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Home')),
      body: Center(
        child: ElevatedButton(
          child: const Text('Send Data'),
          onPressed: () {
            Navigator.push(
              context,
              MaterialPageRoute(
                builder: (context) =>
                    const SecondScreen(message: 'Hello Students'),
              ),
            );
          },
        ),
      ),
    );
  }
}

class SecondScreen extends StatelessWidget {
  const SecondScreen({super.key, required this.message});

  final String message; // set once, by the constructor

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Second Screen')),
      body: Center(child: Text(message)),
    );
  }
}
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 19-20

The first screen creates SecondScreen and gives it the message.

شاشەی یەکەم SecondScreen دروست دەکات و نامەکەی دەداتێ.

Lineدێڕی 31

super.key passes the key to the parent class; required this.message makes the data compulsory.

super.key دەدات بە باوان؛ required this.message ناچاری دەکات.

Lineدێڕی 33

final: set once by the constructor, never changed.

final: یەک جار لە دادەنرێت و هەرگیز ناگۆڕێت.

Lineدێڕی 39

The screen shows the data it received.

شاشەکە ئەو وەریگرتووە پیشان دەدات.

Quick checkپشکنینی خێراWhy is the field final String message; and not String message = '';?بۆچی final String message;ـە نەک String message = '';؟

Getting an answer back: pop with a valueوەرگرتنەوەی وەڵامێک: pop بە نرخێکەوە

Data can also travel back. A screen can ask the user to choose something and return the choice. Two things make this work:

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

  • Navigator.push returns a Future. It completes when the pushed route is popped. await waits for it.
  • Navigator.pop(context, value) takes an optional second argument: the value that completes that Future.
  • Navigator.push دەگەڕێنێتەوە. کاتێک pushکراوەکە pop دەکرێت تەواو دەبێت. await چاوەڕێی دەکات.
  • Navigator.pop(context, value) دووەمی هەڵبژاردەیی وەردەگرێت: ئەو نرخەی کە پێی تەواو دەبێت.
A tea order: the choice comes backداوای چا: هەڵبژاردنەکە دەگەڕێتەوەDARTRuns on a phone (or an emulator)لەسەر مۆبایل کار دەکات
import 'package:flutter/material.dart';

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

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

  @override
  State<OrderScreen> createState() => _OrderScreenState();
}

class _OrderScreenState extends State<OrderScreen> {
  String _order = 'Nothing yet';

  Future<void> _chooseTea() async {
    // push returns a Future that completes when the screen is popped
    final String? choice = await Navigator.push<String>(
      context,
      MaterialPageRoute(builder: (context) => const TeaScreen()),
    );

    if (!mounted) return; // this screen may be gone after the await
    if (choice == null) return; // the user pressed Back without choosing
    setState(() => _order = choice);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Tea House')),
      body: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Text('Your order: $_order'),
            const SizedBox(height: 16),
            FilledButton(
              onPressed: _chooseTea,
              child: const Text('Choose tea'),
            ),
          ],
        ),
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Choose tea')),
      body: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            ElevatedButton(
              onPressed: () => Navigator.pop(context, 'Tea with sugar'),
              child: const Text('With sugar'),
            ),
            const SizedBox(height: 8),
            ElevatedButton(
              onPressed: () => Navigator.pop(context, 'Tea without sugar'),
              child: const Text('Without sugar'),
            ),
          ],
        ),
      ),
    );
  }
}
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 15

An async method, because it waits for the other screen.

async، چونکە چاوەڕێی شاشەکەی تر دەکات.

Lineدێڕی 17-20

push<String> says the route returns a String. await pauses here until TeaScreen is popped; the app keeps running.

push<String> دەڵێت دەگەڕێنێتەوە. await لێرە ڕادەوەستێت تا ⁦TeaScreen pop⁩ دەکرێت؛ بەردەوام کار دەکات.

Lineدێڕی 22

After an await, check mounted before using the State or its context.

دوای await، پێش بەکارهێنانی Stateـەکە یان contextـەکەی mounted بپشکنە.

Lineدێڕی 23

Back without choosing gives null.

Back بەبێ هەڵبژاردن null دەدات.

Lineدێڕی 60

pop with a value: TeaScreen closes and 'Tea with sugar' goes back.

pop بە نرخێکەوە: TeaScreen دادەخرێت و 'Tea with sugar' دەگەڕێتەوە.

Animation in four frames, a phone on the left and the Navigator stack on the right. 1: the stack holds one card, OrderScreen; the phone shows 'Your order: Nothing yet' and a Choose tea button. 2: push adds a TeaScreen card on top; the phone shows two buttons, With sugar and Without sugar; OrderScreen waits at await. 3: the user taps With sugar; the TeaScreen card lifts off the stack and a tag 'Tea with sugar' flies down to the OrderScreen card. 4: one card again; the phone shows 'Your order: Tea with sugar'.
Animation in four frames, a phone on the left and the Navigator stack on the right. 1: the stack holds one card, OrderScreen; the phone shows 'Your order: Nothing yet' and a Choose tea button. 2: push adds a TeaScreen card on top; the phone shows two buttons, With sugar and Without sugar; OrderScreen waits at await. 3: the user taps With sugar; the TeaScreen card lifts off the stack and a tag 'Tea with sugar' flies down to the OrderScreen card. 4: one card again; the phone shows 'Your order: Tea with sugar'.
push adds a card; pop removes it and sends a value back to the screen that waited.push کارتێک زیاد دەکات؛ pop لای دەبات و نرخێک دەگەڕێنێتەوە بۆ ئەو شاشەیەی چاوەڕێی کرد.CêIT

await and Futures are taught in Futures and async. The mounted rule comes from Flutter's cookbook: when you use a context or State after an asynchronous gap, check mounted first.

await و لە Futures و async دەخوێنرێن. یاسای mounted لە cookbookـی هاتووە: کاتێک contextـێک یان Stateـێک دوای بۆشاییەکی بەکار دەهێنیت، سەرەتا mounted بپشکنە.

Quick checkپشکنینی خێراThe user opens TeaScreen and presses the system Back button without tapping a choice. What does await Navigator.push<String>(...) give? TeaScreen دەکاتەوە و بەبێ دەستلێدان لە هەڵبژاردەیەک Backـی سیستەم دەکات. await Navigator.push<String>(...) چی دەدات؟

Replacing and clearing routesگۆڕین و پاککردنەوەی ڕێگەکان

push and pop are enough for most screens. A few other Navigator methods change the stack in other ways:

push و pop بۆ زۆربەی شاشەکان بەسن. چەند تری Navigator بە شێوەی تر دەگۆڕن:

Common Navigator methods باوی Navigator
MethodWhat it does to the stackچی بە دەکاتTypical useبەکارهێنانی باو
push(context, route)Adds a route on top دەخاتە سەرەوەOpen a details screenکردنەوەی شاشەی وردەکاری
pop(context, [result])Removes the top route, optionally with a result سەرەوە لادەبات، دەکرێت ئەنجامێکیش بنێرێتBack, Cancel, SaveBack، Cancel، Save
pushReplacement(context, route)Adds the new route and removes the current one نوێیەکە زیاد دەکات و ئێستاکە لادەباتSplash → home, login → home ← سەرەکی، ← سەرەکی
pushAndRemoveUntil(context, route, predicate)Adds the new route and removes old ones until the predicate says stop; (route) => false removes all نوێیەکە زیاد دەکات و کۆنەکان لادەبات تا predicateـەکە دەڵێت بوەستە؛ (route) => false هەموویان لادەباتLog out
canPop(context)true if there is a route under the current onetrue ئەگەر لە ژێر ئێستاکەوە هەبێتShow or hide your own back buttonپیشاندان یان شاردنەوەی گەڕانەوەی خۆت
maybePop(context)Pops only if the route allows itتەنها ئەگەر ڕازی بێت pop دەکاتA Back button that respects PopScope Back کە ڕێز لە PopScope دەگرێت
Log in and log outچوونەژوورەوە و چوونەدەرەوەDARTRuns on a phone (or an emulator)لەسەر مۆبایل کار دەکات
import 'package:flutter/material.dart';

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: FilledButton(
          onPressed: () {
            // Replace the login screen: Back will not return to it.
            Navigator.pushReplacement(
              context,
              MaterialPageRoute(builder: (context) => const HomeScreen()),
            );
          },
          child: const Text('Log in'),
        ),
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Home')),
      body: Center(
        child: TextButton(
          onPressed: () {
            // Log out: remove every route, then show the login screen.
            Navigator.pushAndRemoveUntil(
              context,
              MaterialPageRoute(builder: (context) => const LoginScreen()),
              (route) => false,
            );
          },
          child: const Text('Log out'),
        ),
      ),
    );
  }
}
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 13-16

After logging in, Back must not return to the login screen: replace it.

دوای ، Back نابێت بگەڕێتەوە بۆ شاشەی : بیگۆڕە.

Lineدێڕی 36-40

On log out, clear the whole stack and start again from the login screen.

لە کاتی ، هەموو پاک بکەرەوە و لە شاشەی دەست پێ بکەرەوە.

The splash screen lesson uses pushReplacement for the same reason: the intro screen should not come back.

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

Quick checkپشکنینی خێراAfter a successful login you call pushReplacement with HomeScreen. What does Navigator.canPop(context) say on HomeScreen?دوای سەرکەوتوو بانگی pushReplacement بە HomeScreenـەوە دەکەیت. Navigator.canPop(context) لە HomeScreenـدا چی دەڵێت؟

Next steps: named routes and go_routerهەنگاوەکانی داهاتوو: ڕێگەکانی ناودار و ⁦go_router⁩

The notes say that Flutter also uses "URLs" for navigation. This means giving each route a name or path, such as /settings. You will meet two ways. Here is a short overview; build your first apps with push and pop.

تێبینییەکان دەڵێن «URL»ـیش بۆ بەکار دەهێنێت. ئەمە واتە دانانی ناو یان بۆ هەر ، وەک /settings. دوو ڕێگا دەبینیت. ئەمە کورتەیەکە؛ یەکەم بە push و pop دروست بکە.

Next steps: named routes and go_routerهەنگاوەکانی داهاتوو: ڕێگەکانی ناودار و ⁦go_router⁩

Named routesڕێگەکانی ناودار

With named routes you list the app's routes once in MaterialApp(routes: …) and open one by its name:

بە ناودار، یەک جار لە MaterialApp(routes: …)ـدا ڕیز دەکەیت و یەکێکیان بە ناوەکەیەوە دەکەیتەوە:

Named routesڕێگەکانی ناودارDARTRuns on a phone (or an emulator)لەسەر مۆبایل کار دەکات
import 'package:flutter/material.dart';

void main() {
  runApp(
    MaterialApp(
      initialRoute: '/',
      routes: {
        '/': (context) => const HomeScreen(),
        '/settings': (context) => const SettingsScreen(),
      },
    ),
  );
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Home')),
      body: Center(
        child: ElevatedButton(
          onPressed: () => Navigator.pushNamed(context, '/settings'),
          child: const Text('Settings'),
        ),
      ),
    );
  }
}

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

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

A map from names to builders. '/' is the first route.

نەخشەیەک لە ناوەکانەوە بۆ builderـەکان. '/' یەکەم .

Lineدێڕی 24

Open a route by its name.

بە ناوەکەیەوە بکەرەوە.

Quick checkپشکنینی خێراWhy does Flutter's documentation not recommend named routes for most apps?بۆچی بەڵگەنامەکانی ناودار بۆ زۆربەی پێشنیار ناکەن؟

🧭📱 Navigation & Routes • Flutter TutorialMitch Koko · Englishئینگلیزی · 83K viewsبینین · 1.8K likesلایک · Partبەشی 0:00–2:00 (ofلە 2:34)

Go to a new page with Navigator.push, then do the same with named routes: a routes map in MaterialApp and Navigator.pushNamed.

چوون بۆ لاپەڕەیەکی نوێ بە Navigator.push، پاشان هەمان کار بە ناودار: Mapـی routes لە MaterialAppـدا و Navigator.pushNamed.

Watch 0:00–2:00: Navigator.push with MaterialPageRoute (0:30), then a routes map in MaterialApp and Navigator.pushNamed (1:05). The video calls named routes easier; this screen explains why Flutter's docs no longer recommend them for most apps. Stops before an advert for his book.

لە ⁦0:00⁩ تا ⁦2:00⁩ سەیر بکە: Navigator.push لەگەڵ MaterialPageRoute ⁦(0:30)⁩، پاشان Mapـی routes لە MaterialAppـدا و Navigator.pushNamed ⁦(1:05)⁩. ڤیدیۆکە دەڵێت ناودار ئاسانترە؛ ئەم شاشەیە ڕوونی دەکاتەوە بۆچی ئیتر بۆ زۆربەی پێشنیاری ناکەن. پێش ڕیکلامی کتێبەکەی ڕادەوەستێت.

Next steps: named routes and go_routerهەنگاوەکانی داهاتوو: ڕێگەکانی ناودار و ⁦go_router⁩

go_router: routes as paths⁦go_router⁩: ڕێگەکان وەک ڕێڕەو

Apps with deep links (a link that opens one particular screen inside the app) or a web version use the Router API, usually through the go_router package from the Flutter team (version 18 in 2026). Each route has a path, like a web address, and you navigate with context.go('/settings'):

ئەو یان وەشانی وێبیان هەیە ⁦Router API⁩ بەکار دەهێنن، زۆرجار لە ڕێگەی ⁦go_router⁩ـەوە کە تیمی دروستی کردووە ( ⁦18⁩ لە ⁦2026⁩). هەر هەیە، وەک ناونیشانی وێب. بە context.go('/settings') دەگوازرێیتەوە بۆ شاشەیەکی تر:

Definitionپێناسە

A link that opens a particular screen inside an , not just its start screen, for example a link to one product in a shop app.

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

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

final _router = GoRouter(
  routes: [
    GoRoute(
      path: '/',
      builder: (context, state) => const HomeScreen(),
      routes: [
        GoRoute(
          path: 'settings', // the full path is /settings
          builder: (context, state) => const SettingsScreen(),
        ),
      ],
    ),
  ],
);

void main() => runApp(MaterialApp.router(routerConfig: _router));

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Home')),
      body: Center(
        child: ElevatedButton(
          onPressed: () => context.go('/settings'),
          child: const Text('Settings'),
        ),
      ),
    );
  }
}

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

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

All routes in one place, each with a path.

هەموو لە یەک شوێندا، هەر یەکە بە .

Lineدێڕی 19

MaterialApp.router hands navigation to the router.

MaterialApp.router دەداتە دەست routerـەکە.

Lineدێڕی 30

Go to a path. A link like myapp://…/settings can open the same screen.

بڕۆ بۆ . وەک myapp://…/settings دەتوانێت هەمان شاشە بکاتەوە.

Quick checkپشکنینی خێراWhich choice fits a shop app whose web links must open one product's page directly?کام هەڵبژاردە لەگەڵ فرۆشگادا دەگونجێت کە وێبەکەی دەبێت ڕاستەوخۆ لاپەڕەی یەک کاڵا بکەنەوە؟

go_router (Package of the Week)Flutter · Englishئینگلیزی · 178K viewsبینین · 4.5K likesلایک

What go_router is: routes written as paths like web addresses, going to a screen with context.go, and nested routes for a bottom bar.

go_router چییە: وەک دەنووسرێن، هاوشێوەی ، چوون بۆ شاشەیەک بە context.go و لە ناو یەکتردا بۆ .

The whole 1:48 official clip: configuring GoRoute paths (0:23), navigating (0:43), shell routes (1:00).

هەموو کلیپە فەرمییەکە ⁦(1:48)⁩: دانانی GoRoute ⁦(0:23)⁩، ⁦(0:43)⁩ و ShellRoute ⁦(1:00)⁩.

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

MistakeهەڵەWhat happensچی ڕوو دەداتFixچاککردن
RaisedButton(color: …) from old tutorialsRaisedButton(color: …) لە فێرکارییە کۆنەکانەوەCompile error: the class no longer exists کۆمپایل: ئەو چیتر نییەElevatedButton(style: ElevatedButton.styleFrom(backgroundColor: …))ElevatedButton(style: ElevatedButton.styleFrom(backgroundColor: …))
A non-final field in a screen widget (String getData = '';) ناfinal لە شاشەدا (String getData = '';)A must_be_immutable warning; data can silently be emptyئاگاداریی must_be_immutable؛ دەکرێت بێدەنگ بەتاڵ بێتfinal String message; + required this.messagefinal String message; + required this.message
Forgetting await before Navigator.push when you need the resultلەبیرچوونی await پێش Navigator.push کاتێک ئەنجامەکەت پێویستەYou get a Future, not the value وەردەگریت، نەک نرخەکەfinal result = await Navigator.push<String>(…);final result = await Navigator.push<String>(…);
Using context or setState after await without a checkبەکارهێنانی context یان setState دوای await بەبێ پشکنینAn error if the screen was closed meanwhile ئەگەر لەم ماوەیەدا شاشەکە داخرابێتif (!mounted) return; (or context.mounted)if (!mounted) return; (یان context.mounted)
Not handling null from a popped routeمامەڵە نەکردن لەگەڵ null لە popکراوەوە"null" shown on screen, or a crash«null» لەسەر شاشە دەردەکەوێت، یان دەتەقێتUse String? and check for nullString? بەکار بهێنە و null بپشکنە
push from a splash or login screenpush لە یان شاشەی Back returns to the splash or login screenBack دەگەڕێتەوە بۆ یان شاشەی pushReplacementpushReplacement
Calling pop on the first routeبانگکردنی pop لەسەر یەکەم The stack is left empty: the user sees a black screen, and the app does not close بەتاڵ دەبێت: شاشەیەکی ڕەش دەبینێت و داناخرێتCheck Navigator.canPop(context) first, or use maybePop, which does nothing on the first routeسەرەتا Navigator.canPop(context) بپشکنە، یان maybePop بەکار بهێنە کە لەسەر یەکەم هیچ ناکات

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

Exerciseڕاهێنان1. Follow the stack١. شوێن ستاکەکە بکەوە

The app starts on Home. The user does: push(Products), push(Details), pop(), push(Cart), pop(), pop(). Write the stack after each step and the screen the user sees at the end.

لە Homeـەوە دەست پێ دەکات. ئەمانە دەکات: ⁦push(Products)⁩، ⁦push(Details)⁩، ⁦pop()⁩، ⁦push(Cart)⁩، ⁦pop()⁩، ⁦pop()⁩. دوای هەر هەنگاوێک و ئەو شاشەیەی لە کۆتاییدا دەیبینێت بنووسە.

Show answerوەڵامەکە پیشان بدە
StepهەنگاوStack (bottom → top, left to right) (لە چەپەوە بۆ ڕاست: لە خوارەوە بۆ سەرەوە)
push(Products)Home, Products
push(Details)Home, Products, Details
pop()Home, Products
push(Cart)Home, Products, Cart
pop()Home, Products
pop()Home

At the end the user sees Home.

لە کۆتاییدا Home دەبینێت.

Exerciseڕاهێنان2. Modernise the notes' two screens٢. دوو شاشەکەی تێبینییەکان نوێ بکەرەوە

The notes' FirstRoute uses RaisedButton(child: Text('Click Here'), color: Colors.orangeAccent, onPressed: …). Rewrite the button for today's Flutter and fill in its onPressed so it opens SecondRoute.

FirstRouteـی تێبینییەکان RaisedButton(child: Text('Click Here'), color: Colors.orangeAccent, onPressed: …) بەکار دەهێنێت. بۆ ئەمڕۆ بنووسەرەوە و onPressedـەکەی پڕ بکەرەوە بۆ ئەوەی SecondRoute بکاتەوە.

Show answerوەڵامەکە پیشان بدە
DART
ElevatedButton(
  style: ElevatedButton.styleFrom(
    backgroundColor: Colors.orangeAccent,
  ),
  onPressed: () {
    Navigator.push(
      context,
      MaterialPageRoute(builder: (context) => const SecondRoute()),
    );
  },
  child: const Text('Click Here'),
)
Exerciseڕاهێنان3. Pass an object٣. ئۆبجێکتێک بنێرە

A shop shows a list of products (name and price). Tapping one opens a ProductScreen that shows its name in the app bar and its price in the body. Pass the whole product, not two separate strings.

فرۆشگایەک لیستێکی کاڵاکان (ناو و نرخ) پیشان دەدات. دەستلێدان لە یەکێکیان ProductScreen دەکاتەوە کە ناوەکەی لە و نرخەکەی لە bodyـدا پیشان دەدات. هەموو کاڵاکە بنێرە، نەک دوو جیا.

Hintئاماژە

Make a Product class with final fields, and give ProductScreen a required this.product parameter.

Product بە final دروست بکە و required this.product بدە بە ProductScreen.

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

class Product {
  const Product(this.name, this.price);

  final String name;
  final int price; // in Iraqi dinars
}

const products = [
  Product('Notebook', 1500),
  Product('Pen', 500),
  Product('Bag', 12000),
];

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Shop')),
      body: ListView(
        children: [
          for (final product in products)
            ListTile(
              title: Text(product.name),
              onTap: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(
                    builder: (context) => ProductScreen(product: product),
                  ),
                );
              },
            ),
        ],
      ),
    );
  }
}

class ProductScreen extends StatelessWidget {
  const ProductScreen({super.key, required this.product});

  final Product product;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(product.name)),
      body: Center(child: Text('Price: ${product.price} IQD')),
    );
  }
}
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 3-8

A small immutable class for one product.

بچووکی بۆ یەک کاڵا.

Lineدێڕی 32

The tapped product goes into the constructor.

ئەو کاڵایەی دەستی لێ درا دەچێتە ناو .

Lineدێڕی 44-46

final Product product; with required this.product.

final Product product; لەگەڵ required this.product.

Exerciseڕاهێنان4. Return a value٤. نرخێک بگەڕێنەرەوە

A settings screen has two buttons, Kurdish and English. Write the code that opens it from the home screen, waits for the choice, and shows it in a Text (Language: Kurdish). What does your code do if the user presses Back?

شاشەیەکی ڕێکخستن دوو هەیە، Kurdish و English. ئەو کۆدە بنووسە کە لە شاشەی سەرەکییەوە دەیکاتەوە، چاوەڕێی هەڵبژاردنەکە دەکات و لە Textـێکدا پیشانی دەدات (Language: Kurdish). ئەگەر Back بکات کۆدەکەت چی دەکات؟

Show answerوەڵامەکە پیشان بدە
DART
// in the home screen's State
String _language = 'English';

Future<void> _chooseLanguage() async {
  final String? choice = await Navigator.push<String>(
    context,
    MaterialPageRoute(builder: (context) => const LanguageScreen()),
  );
  if (!mounted || choice == null) return; // Back: keep the old language
  setState(() => _language = choice);
}

// in LanguageScreen
ElevatedButton(
  onPressed: () => Navigator.pop(context, 'Kurdish'),
  child: const Text('Kurdish'),
),

If the user presses Back, choice is null, the method returns, and the old language stays.

ئەگەر Back بکات، choice nullـە، دەگەڕێتەوە و زمانە کۆنەکە دەمێنێتەوە.

Exerciseڕاهێنان5. Which method?٥. کام میتۆد؟

Choose push, pop, pushReplacement or pushAndRemoveUntil for each: (a) open a photo in full screen; (b) close a form after Save and send the new item back; (c) after a successful login; (d) after Log out, from a screen deep in the app.

بۆ هەر یەکێک push، pop، pushReplacement یان pushAndRemoveUntil هەڵبژێرە: (أ) کردنەوەی وێنەیەک بە پڕبەشاشە؛ (ب) داخستنی فۆرمێک دوای Save و ناردنەوەی بڕگە نوێیەکە؛ (ج) دوای سەرکەوتوو؛ (د) دوای ، لە شاشەیەکی قووڵی .

Show answerوەڵامەکە پیشان بدە
  • (a) push
  • (b) pop(context, newItem)
  • (c) pushReplacement, so Back does not return to the login screen
  • (d) pushAndRemoveUntil(…, (route) => false), to clear every screen
  • (أ) push
  • (ب) pop(context, newItem)
  • (ج) pushReplacement، بۆ ئەوەی Back نەگەڕێتەوە بۆ شاشەی
  • (د) pushAndRemoveUntil(…, (route) => false)، بۆ پاککردنەوەی هەموو شاشەکان
Quick checkپشکنینی خێراWhich object completes the Future returned by Navigator.push?کام شت تەواو دەکات کە Navigator.push دەیگەڕێنێتەوە؟

Summaryپوختە

  • Navigation moves the user between screens. In Flutter, screens are routes, and routes are widgets.
  • The Navigator (made by MaterialApp) keeps routes in a stack; the top route is on the screen.
  • Navigator.push(context, MaterialPageRoute(builder: …)) adds a route; Navigator.pop(context) removes the top one. The AppBar's back arrow and the system Back also pop.
  • Send data forward through the next screen's constructor: a final field, required this.x, super.key.
  • Get data back with final result = await Navigator.push<T>(…) and Navigator.pop(context, value); check mounted and null.
  • pushReplacement and pushAndRemoveUntil replace or clear routes (splash, login, logout).
  • Named routes exist but are not recommended for most apps; for deep links and the web, use the Router API with go_router.
  • لە نێوان شاشەکاندا دەگوازێتەوە. لە ، شاشەکان و .
  • Navigator (کە MaterialApp دروستی دەکات) لە هەڵدەگرێت؛ سەرەوە لەسەر شاشەیە.
  • Navigator.push(context, MaterialPageRoute(builder: …)) زیاد دەکات؛ Navigator.pop(context) ئەوەی سەرەوە لادەبات. تیری گەڕانەوەی AppBar و Backـی سیستەمیش pop دەکەن.
  • بە شاشەی داهاتوودا بنێرە پێشەوە: final، required this.x، super.key.
  • بە final result = await Navigator.push<T>(…) و Navigator.pop(context, value) وەربگرەوە؛ mounted و null بپشکنە.
  • pushReplacement و pushAndRemoveUntil دەگۆڕن یان پاک دەکەنەوە (، ، ).
  • ناودار هەن بەڵام بۆ زۆربەی پێشنیار ناکرێن؛ بۆ و وێب، ⁦Router API⁩ بە ⁦go_router⁩ـەوە بەکار بهێنە.
Review questionsپرسیارەکانی پێداچوونەوە
What is the difference between MaterialPageRoute and Navigator?جیاوازیی نێوان MaterialPageRoute و Navigator چییە؟

MaterialPageRoute is one route (a page with its animation). Navigator is the widget that keeps the routes in a stack and has push and pop.

MaterialPageRoute یەک (لاپەڕەیەک بە ). Navigator ئەو کە لە هەڵدەگرێت و push و popـی هەیە.

How does the second screen receive data?شاشەی دووەم چۆن دراوە وەردەگرێت؟

Through its constructor: the first screen writes SecondScreen(message: 'Hello Students') inside the route's builder.

لە ڕێگەی : شاشەی یەکەم لەناو builderـی SecondScreen(message: 'Hello Students') دەنووسێت.

What does await Navigator.push return if the user presses Back?ئەگەر بەکارهێنەرەکە Back بکات await Navigator.push چی دەگەڕێنێتەوە؟

null, because the route was popped without a value.

null، چونکە بەبێ نرخ pop کرا.

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

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

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

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

Opening Links and Other Apps with url_launcherکردنەوەی بەستەرەکان و ئەپەکانی تر بە ⁦url_launcher⁩

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

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