Navigasi dan Hero Animation Flutter
Pada aplikasi mobile, sering kali kita memiliki banyak halaman atau layar.
Proses perpindahan antar layar tersebut dinamakan navigasi.
Hero Animation adalah animasi bawaan flutter yang dapat langsung digunakan.
Jenis Navigasi
Pada tahapan ini kita akan coba membahas beberapa metode navigasi yang biasa digunakan.
info
- Basic Navigation
- Named Navigation
- Routed Navigation
Prinsip Navigasi
Ada prinsip dasar terkait navigasi, yaitu stack:
Konsep
Ada 2 Jenis Stack:
- Pop
- Menumpukkan Stack atau Tumpukan Baru
- Push
- Membuang Stack Teratas
Contoh Pop:

Contoh Push:

Struktur Project

lib/screens/pertama.dart
import 'package:belajar_navigasi/screens/kedua.dart';import 'package:flutter/material.dart';class LayarPertama extends StatelessWidget { const LayarPertama({Key? key}) : super(key: key); Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Layar Pertama'), ), body: Center( child: ElevatedButton( child: const Text('Ke Layar 2'), onPressed: () { // Pada Line ini akan kita isi Perintah Navigasi Push }, ), ), ); }}lib/screens/kedua.dart
import 'package:flutter/material.dart';class LayarKedua extends StatelessWidget { const LayarKedua({Key? key}) : super(key: key); Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Layar Kedua'), ), body: Center( child: ElevatedButton( child: const Text('Kembali'), onPressed: () { // Pada Line ini akan kita isi Perintah Navigasi Pop }, ), ), ); }}lib/main.dart
import 'package:belajar_navigasi/screens/pertama.dart';import 'package:flutter/material.dart';void main() { runApp(const MyApp());}class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue ), home: const LayarPertama() ); }}Basic Navigation
info
- Berpindah antara widget/screen 1 ke widget lain nya
- Menggunakan class Navigator dari API Flutter
- Method push → menuju layar baru
- Method pop → kembali ke layar sebelumnya
Push
lib/screens/pertama.dart
import 'package:belajar_navigasi/screens/kedua.dart';import 'package:flutter/material.dart';class LayarPertama extends StatelessWidget { const LayarPertama({Key? key}) : super(key: key); Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Layar Pertama'), ), body: Center( child: ElevatedButton( child: const Text('Ke Layar 2'), onPressed: () { Navigator.push( context, MaterialPageRoute(builder: (context) => const LayarKedua()) ); }, ), ), ); }}Pop
lib/screens/kedua.dart
import 'package:flutter/material.dart';class LayarKedua extends StatelessWidget { const LayarKedua({Key? key}) : super(key: key); Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Layar Kedua'), ), body: Center( child: ElevatedButton( child: const Text('Kembali'), onPressed: () { Navigator.pop(context); }, ), ), ); }}With Data
Pada jenis navigasi ini kita dapat mengirim data dengan cara:
- Menggunakan Navigator
- Menambahkan Argument ke Widget/Layar Tujuan
- Mendeklarasikan Variable Penerima Argument tersebut di Layar Tujuan
lib/screens/kedua.dart
import 'package:flutter/material.dart';class LayarKedua extends StatelessWidget { const LayarKedua({Key? key, required this.kutipan}) : super(key: key); final String kutipan; Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Layar Kedua'), ), body: Container( alignment: Alignment.center, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text( kutipan, style: const TextStyle( fontSize: 20 ), ), ElevatedButton( onPressed: () { Navigator.pop(context); }, child: const Text('Kembali') ) ], ), ) ); }}lib/screens/pertama.dart
import 'package:belajar_navigasi/screens/kedua.dart';import 'package:flutter/material.dart';class LayarPertama extends StatelessWidget { const LayarPertama({Key? key}) : super(key: key); Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Layar Pertama'), ), body: Center( child: ElevatedButton( child: const Text('Ke Layar 2'), onPressed: () { Navigator.push( context, MaterialPageRoute(builder: (context) => const LayarKedua(kutipan: 'Data Dari Layar 1')) ); }, ), ), ); }}Hasil

Named Routed Navigation
info
- Membuat Route di bagian awal Aplikasi
- Ada initialRoute → Route yang akan di eksekusi pertama kali
- ada routes → daftar route yang kita buat
- Method pushNamed → menuju layar baru menggunakan nama rute
Define Route
lib/main.dart
import 'package:belajar_navigasi/screens/kedua.dart';import 'package:belajar_navigasi/screens/pertama.dart';import 'package:flutter/material.dart';void main() { runApp(const MyApp());}class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue ), initialRoute: '/', routes: { '/': (context) => const LayarPertama(), '/kedua': (context) => const LayarKedua() } ); }}Push
lib/screens/pertama.dart
import 'package:belajar_navigasi/screens/kedua.dart';import 'package:flutter/material.dart';class LayarPertama extends StatelessWidget { const LayarPertama({Key? key}) : super(key: key); Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Layar Pertama'), ), body: Center( child: ElevatedButton( child: const Text('Ke Layar 2'), onPressed: () { Navigator.pushNamed(context, '/kedua'); }, ), ), ); }}With Data
Pada jenis navigasi ini kita dapat mengirim data dengan cara:
- Menggunakan property argument
- Menggunakan method ModalRoute.of()
- mengembalikan route sekarang dengan arguments nya
- Deklarasikan Variable di widget tujuan
- untuk menampung nilai
lib/screens/pertama.dart
import 'package:belajar_navigasi/screens/kedua.dart';import 'package:flutter/material.dart';class LayarPertama extends StatelessWidget { const LayarPertama({Key? key}) : super(key: key); Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Layar Pertama'), ), body: Center( child: ElevatedButton( child: const Text('Ke Layar 2'), onPressed: () { Navigator.pushNamed( context, '/kedua', arguments: 'Data Dari Layar 1' ); }, ), ), ); }}lib/screens/kedua.dart
import 'package:flutter/material.dart';class LayarKedua extends StatelessWidget { const LayarKedua({Key? key}) : super(key: key); Widget build(BuildContext context) { // Ambil Data Argument final args = ModalRoute.of(context)!.settings.arguments as String; return Scaffold( appBar: AppBar( title: const Text('Layar Kedua'), ), body: Container( alignment: Alignment.center, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text( args, style: const TextStyle( fontSize: 20 ), ), ElevatedButton( onPressed: () { Navigator.pop(context); }, child: const Text('Kembali') ) ], ), ) ); }}Hasil

Hero Animation
Animasi Default dari Flutter
lib/screens/pertama.dart
import 'package:belajar_navigasi/screens/kedua.dart';import 'package:flutter/material.dart';class LayarPertama extends StatelessWidget { const LayarPertama({Key? key}) : super(key: key); Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Layar Pertama'), ), body: Container( padding: EdgeInsets.all(10), child: GestureDetector( child: Hero( tag: 'gambarHero', child: Image.network('https://picsum.photos/250?image=9'), ), onTap: () { Navigator.pushNamed( context, '/kedua', arguments: 'Data Dari Layar 1' ); }, ), ) ); }}lib/screens/kedua.dart
import 'package:flutter/material.dart';class LayarKedua extends StatelessWidget { const LayarKedua({Key? key}) : super(key: key); Widget build(BuildContext context) { // Ambil Data Argument final args = ModalRoute.of(context)!.settings.arguments as String; return Scaffold( appBar: AppBar( title: const Text('Layar Kedua'), ), body: Container( alignment: Alignment.center, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Hero( tag: 'gambarHero', child: Image.network('https://picsum.photos/250?image=9') ), Text( args, style: const TextStyle( fontSize: 20 ), ), ElevatedButton( onPressed: () { Navigator.pop(context); }, child: const Text('Kembali') ) ], ), ) ); }}Hasil
