Navigation & Routing : Multiple Screen

A. Tujuan

Tujuan praktikum ini yaitu mahasiswa mampu menguasi konsep Navigation dan Routing pada Flutter:

1. Membuat aplikasi yang dapat berpindah dari halaman satu ke halaman lain

2. Membuat aplikasi yang dapat mengirim dan menerima data dari halaman lain

B. Alat

Computer / laptop yang telah terinstall lingkungan flutter development

C. Teori

C.1 Navigation dan Routing Flutter

Navigation atau Navigasi merupakan sebuah proses berpindah dari satu halaman (screen/page) ke halaman lain dalam sebuah aplikasi flutter, misalkan perpindahan dari halaman login aplikasi ke halaman utama aplikasi ketika tombol login ditekan atau proses perpindahan dari halaman produk ke halaman detail produk dan proses kembalinya dari halaman detail produk ke halaman produk. Navigasi pada flutter menggunakan widget Navigator yang mana bekerja menggunakan konsep tumpukan (stack), Gambar berikut ini merupakan konsep dasar navigasi pada flutter.

Gambar Konsep Dasar Navigasi Flutter

Berdasarkan gambar diatas maka dapat dijelaskan sebagai berikut.

1. Halaman awal aplikasi flutter akan berada pada posisi dasar, pada contoh diatas adalah halaman product.

2. Ketika akan berpindah ke halaman baru, flutter akan menggunakan perintah push sehingga halaman baru akan berada diatas tumpukan halaman sebelumnya, contohnya Ketika sedang berada pada halaman product kemudian berpindah ke halaman detail product maka secara otomatis halaman detail product akan berada diatas halaman product.

3. Ketika pada halaman detail product menekan tombol Kembali maka flutter akan menggunakan perintah pop dan halaman detail flutter akan dikeluarkan dari tumpukkan dan akan muncul halaman sebelumnya yaitu halaman product.

Routing atau Rute adalah sebuah sistem yang digunakan untuk mendefinisikan dan mengelola routes dalam aplikasi, setiap route didefinisikan sehingga Ketika akan memanggil halaman cukup dengan memanggil nama route tersebut, hal ini mempermudah dalam mengelola route tanpa harus membuat instance baru setiap kali akan memanggil suatu halaman.

C.2 Jenis Routing pada Flutter

C.2.1 Navigator (Anonymous Routes)

Widget Navigation menampilkan halaman dengan konsep tumpukan menggunakan animasi transisi Ketika berpindah ke halaman, untuk berpindah ke halaman baru diakses melalui BuildContext dengan memanggil method seperti push() atau pop() secara langsung.

Push()

Center(
  child: ElevatedButton(
    onPressed: () {
      Navigator.push(
        context,
        MaterialPageRoute(builder: (context) => const ProductDetail()),
      );
    },
    child: const Text('Go to Product Detail'),
  ),
),

Pop()

Center(
  child: ElevatedButton(
    onPressed: () {
      Navigator.pop(context);
    },
    child: const Text('Back to Product'),
  ),
),

C.2.2 Named Routes

Named Routes atau Rute Bernama mengelola route pada widget MateriapApp atau CupertinoApp kemudian memanggilnya berdasarkan nama yang telah diberikan, berikut contoh penggunaan named routes pada Flutter.

Definisikan Routes pada MateriapApp

return MaterialApp(
  initialRoute: '/',
  routes: {
    '/': (context) => const Product(),
    '/product_detail': (context) => const ProductDetail(),
  },
);

Menggunakan Named Routes

onPressed: () {
  Navigator.pushNamed(context, '/product_detail');
},

C.2.3 Generated Routes

Generated Routes yang sebuah mekanisme mengelola routes dengan mengirimkan paremeter dan handle error.

MaterialApp(
  onGenerateRoute: (settings) {
    if (settings.name == '/detail') {
      final args = settings.arguments as Map;
      return MaterialPageRoute(
        builder: (context) => DetailPage(data: args['data']),
      );
    }
    return MaterialPageRoute(builder: (context) => NotFoundPage());
  },
);

C.3 Jenis Method Navigation

C.3.1 Push dan Pop

// Push - Menambahkan halaman baru
Navigator.push(context, route);

// Pop - Kembali ke halaman sebelumnya
Navigator.pop(context);

// Pop dengan mengirim data kembali
Navigator.pop(context, 'data yang dikembalikan');

C.3.2 Push Replacement

// Mengganti halaman saat ini dengan halaman baru
Navigator.pushReplacement(
  context,
  MaterialPageRoute(builder: (context) => LoginPage()),
);

C.3.3 Push and Remove Until

// Menghapus semua halaman sebelumnya
Navigator.pushAndRemoveUntil(
  context,
  MaterialPageRoute(builder: (context) => HomePage()),
  (route) => false, // Hapus semua
);

C.4 Mengirim dan Menerima Data

C.4.1 Mengirim Data

// Dengan constructor
Navigator.push(
  context,
  MaterialPageRoute(
    builder: (context) => DetailPage(id: 123, name: Masnoer),
  ),
);

// Dengan named routes dan arguments
Navigator.pushNamed(
  context,
  '/detail',
  arguments: {'id': 123, 'name': 'Masnoer'},
);

C.4.2 Menerima Data dengan Constructor

class DetailPage extends StatelessWidget {
  final int id;
  final String name;
  
  DetailPage({required this.id, required this.name});
  
  @override
  Widget build(BuildContext context) {
    // Atau ambil dari arguments
    final args = ModalRoute.of(context)!.settings.arguments as Map;
    
    return Scaffold(
      appBar: AppBar(title: Text('Detail: $name')),
      body: Text('ID: $id'),
    );
  }
}

C.4.3 Menerima Data menggunakan ModalRoute.of(context)

class DetailPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // Ambil arguments dari route
    final args = ModalRoute.of(context)!.settings.arguments as Map;
    
    // Akses data
    final int id = args['id'];
    final String name = args['name'];
    
    return Scaffold(
      appBar: AppBar(title: Text('Detail Page')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('ID: $id', style: TextStyle(fontSize: 20)),
            Text('Name: $name', style: TextStyle(fontSize: 20)),
          ],
        ),
      ),
    );
  }
}

D. Langkah-langkah

D.1 Multiple Screen

1. Buat file dart baru

2. Buat class menggunakan stateless widget dengan nama MyNav

3. Inisialisasi route pada MaterialApp

return MaterialApp(
  initialRoute: '/',
  routes: {
    '/': (context) => const Product(),
    '/product_detail': (context) => const ProductDetail(),
  },
);

4. Buat class Product dan ProductDetail

Kode Program Lengkap Navigation dan Routing :

import 'package:flutter/material.dart';

void main() => runApp(const MyNav());

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      initialRoute: '/',
      routes: {
        '/': (context) => const Product(),
        '/product_detail': (context) => const ProductDetail(),
      },
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Product'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pushNamed(context, '/product_detail');
          },
          child: const Text('Go to Product Detail'),
        ),
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Product Detail'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pop(context);
          },
          child: const Text('Back to Product'),
        ),
      ),
    );
  }
}

D.2 Mengirim dan Menerima Data

1. Buat file dart baru

2. Inisialisasi route pada MaterialApp

return MaterialApp(
  initialRoute: '/',
  routes: {
    '/': (context) => const HomePage(), // Pindahkan home ke routes
    '/product': (context) => const MyProduct(),
  },
);

3. Buat class baru Homepage, MyProfile, MyProduct

4. Pada class Homepage, pindah ke halaman MyProfile dengan mengirimkan data ID dan Name Ketika diklik tombol Profile melalui constructor.

ElevatedButton(
  onPressed: () {
    Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => const MyProfile(id: 1, name: 'Masnoer'),
      ),
    );
  },
  child: const Text('Profile'),
),

5. Menerima dan menampilkan data dari HomePage pada MyProfile

class MyProfile extends StatelessWidget {
  final int id;
  final String name;
  const MyProfile({super.key, required this.id, required this.name});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Profile'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('ID: $id'),
            Text('Name: $name'),
          ],
        ),
      ),
    );
  }
}

6. Pada class Homepage, pindah ke halaman MyProduct dengan mengirimkan data ID dan Name Ketika diklik tombol Product menggunakan named routes

ElevatedButton(
  onPressed: () {
    Navigator.pushNamed(
      context,
      '/product',
      arguments: {'id': 101, 'name': 'Laptop'},
    );
  },
  child: const Text('Product'),
),

7. Menerima dan menampilkan data dari HomePage pada MyProduct

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

  @override
  Widget build(BuildContext context) {
    final args = ModalRoute.of(context)!.settings.arguments as Map?;
    final int id = args?['id'] ?? 0;
    final String name = args?['name'] ?? 'Unknown';

    return Scaffold(
      appBar: AppBar(
        title: const Text('Product'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('Product ID: $id'),
            Text('Product Name: $name'),
          ],
        ),
      ),
    );
  }
}

Tugas

Link https://github.com/AbyssWatcher07/Aplikasi_Mobile/blob/main/lib/tugas_praktikum4.dart