Navigation & Routing: Multiple Screen dalam Flutter

Konsep Navigation & Routing Flutter

Navigation

Proses berpindah dari satu halaman (screen/page) ke halaman lain dalam aplikasi Flutter. Menggunakan konsep tumpukan (stack) dengan widget Navigator.

Routing

Sistem untuk mendefinisikan dan mengelola routes dalam aplikasi. Mempermudah pengelolaan route tanpa membuat instance baru setiap kali memanggil halaman.

Push & Pop

Push: Menambahkan halaman baru ke tumpukan navigasi. Pop: Mengeluarkan halaman saat ini dari tumpukan dan kembali ke halaman sebelumnya.

Data Passing

Mengirim dan menerima data antar halaman menggunakan constructor atau arguments melalui named routes.

Langkah Implementasi sesuai Modul

A
Navigation Dasar dengan Named Routes

Implementasi navigasi sederhana antara halaman Product dan ProductDetail:

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'),
        ),
      ),
    );
  }
}
Dokumentasi Implementasi:

Halaman Product

Halaman Product

Halaman Product Detail

Halaman Product Detail
B
Mengirim dan Menerima Data antar Halaman

Implementasi pengiriman data menggunakan constructor dan named routes:

import 'package:flutter/material.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      initialRoute: '/',
      routes: {
        '/': (context) => const HomePage(),
        '/product': (context) => const MyProduct(),
      },
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Home Page')),
      body: Center(
        child: Row(
          children: [
            // Mengirim data dengan constructor
            ElevatedButton(
              onPressed: () {
                Navigator.push(
                  context, 
                  MaterialPageRoute(
                    builder: (context) => const MyProfile(id: 1, name: 'Rifki'),
                  ),
                );
              }, 
              child: const Text('Profile'),
            ), 
            // Mengirim data dengan named routes
            ElevatedButton(
              onPressed: () {
                Navigator.pushNamed(
                  context, 
                  '/product',
                  arguments: {'id': 101, 'name': 'Laptop'},
                );
              }, 
              child: const Text('Product'),
            ),
          ],
        ),
      ),
    );
  }
}

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'),
          ],
        ),
      ),
    );
  }
}

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'),
          ],
        ),
      ),
    );
  }
}
Dokumentasi Data Passing:

Halaman Home

Halaman Home

Profile (Constructor)

Halaman Profile

Product (Named Routes)

Halaman Product dengan Data

Tugas: Aplikasi Login dengan Navigation dan Drawer

1
Implementasi Halaman Login dan Navigation

Berikut adalah implementasi aplikasi login dengan navigation dan drawer:

import 'package:flutter/material.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      initialRoute: '/',
      routes: {
        '/': (context) => const LoginPage(),
        '/home': (context) => const HomePage(),
      },
    );
  }
}

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

  @override
  State createState() => _LoginPageState();
}

class _LoginPageState extends State {
  final TextEditingController _usernameController = TextEditingController();
  final TextEditingController _passwordController = TextEditingController();

  void _login() {
    String username = _usernameController.text;
    String password = _passwordController.text;

    Navigator.pushNamed(
      context,
      '/home',
      arguments: {'username': username, 'password': password},
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Login')),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            TextField(
              controller: _usernameController,
              decoration: const InputDecoration(labelText: 'Username'),
            ),
            TextField(
              controller: _passwordController,
              decoration: const InputDecoration(labelText: 'Password'),
              obscureText: true,
            ),
            const SizedBox(height: 20),
            ElevatedButton(onPressed: _login, child: const Text('Login')),
          ],
        ),
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    final args = ModalRoute.of(context)!.settings.arguments as Map?;
    final username = args?['username'] ?? '';
    final password = args?['password'] ?? '';

    return Scaffold(
      appBar: AppBar(title: const Text('Halaman Utama')),
      drawer: Drawer(
        child: ListView(
          padding: EdgeInsets.zero,
          children: [
            DrawerHeader(
              decoration: const BoxDecoration(color: Colors.blue),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  const Text(
                    'Menu',
                    style: TextStyle(color: Colors.white, fontSize: 24),
                  ),
                  const SizedBox(height: 10),
                  Text(
                    'Username: $username',
                    style: const TextStyle(color: Colors.white),
                  ),
                ],
              ),
            ),
            ListTile(
              leading: const Icon(Icons.person),
              title: const Text('Profile'),
              onTap: () {
                Navigator.pop(context);
                showDialog(
                  context: context,
                  builder: (context) => AlertDialog(
                    title: const Text('Profile'),
                    content: Text('Username: $username\nPassword: $password'),
                    actions: [
                      TextButton(
                        onPressed: () => Navigator.pop(context),
                        child: const Text('Close'),
                      ),
                    ],
                  ),
                );
              },
            ),
            ListTile(
              leading: const Icon(Icons.info),
              title: const Text('About'),
              onTap: () {
                Navigator.pop(context);
                showAboutDialog(
                  context: context,
                  applicationName: 'Aplikasi Praktikum',
                  applicationVersion: '1.0.0',
                  applicationLegalese: '© 2025 MyApp',
                  children: [
                    const Padding(
                      padding: EdgeInsets.only(top: 16.0),
                      child: Text(
                        'Aplikasi ini dibuat untuk praktikum Navigation & Routing Flutter.',
                      ),
                    ),
                  ],
                );
              },
            ),
            ListTile(
              leading: const Icon(Icons.logout),
              title: const Text('Logout'),
              onTap: () {
                Navigator.pop(context);
                Navigator.popUntil(context, ModalRoute.withName('/'));
              },
            ),
          ],
        ),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('Username: $username'), 
            Text('Password: $password')
          ],
        ),
      ),
    );
  }
}
Dokumentasi Tugas:

Halaman Login

Halaman Login

Halaman Utama

Halaman Utama

Halaman Utama dengan Drawer

Halaman Utama dengan Drawer

Dialog Profile

Dialog Profile

Dialog About

Dialog About

Kesimpulan

Dalam praktikum Navigation & Routing Flutter ini, kita telah mempelajari:

  1. Konsep dasar navigation dan routing dalam Flutter menggunakan stack
  2. Implementasi navigasi sederhana dengan named routes antara halaman
  3. Teknik mengirim dan menerima data antar halaman menggunakan constructor dan arguments
  4. Pembuatan aplikasi login dengan mekanisme navigasi yang kompleks
  5. Implementasi drawer navigation dengan berbagai menu dan dialog
  6. Penggunaan widget-widget navigation seperti AlertDialog dan AboutDialog

Pemahaman tentang navigation dan routing sangat penting dalam pengembangan aplikasi Flutter karena memungkinkan kita membuat aplikasi dengan multiple screen yang terstruktur dan mudah dikelola. Dengan menguasai konsep ini, kita dapat membuat user experience yang lebih baik dengan transisi yang smooth antar halaman.

Untuk kode lengkap praktikum dapat diakses pada repository GitHub: https://github.com/Alone1011/2311532011-RifkiY-MobileApp.git

Komentar (0)

Tinggalkan Komentar