Navigation dan routing memiliki fungsi untuk menentukan bagaimana alur atau mekanisme peralihan dari suatu screen ke screen lainnya. Misalnya dari splash screen ke halaman login, dari halaman login ke home page, dst.
Di tulisan kali ini, kita akan membuat navigasi sederhana, seperti berikut:

Nah kita langsung saja ke project flutternya, Yuk Ngoding
1. Buat project flutter baru
Bagian ini bisa dilakukan seperti biasanya ya.
2. Class PageRoutes
Disini kita akan membuat file PageRoutes.dart yang memiliki fungsi penamaan dari route (screen tujuan) yang ada pada aplikasi kita.
class PageRoutes {
static const param1 = "param1";
static const param2 = "param2";
static const linkHome = "/";
static const linkDetail = "/Detail";
static const linkSubDetail = "/SubDetail";
}
- linkHome, linkDetail, dan linkSubDetail akan kita gunakan sebagai nama dari perutean dari widget tujuan.
- param1 dan param2 digunakan sebagai key ketika mengirim data antar screen.
3. Widget
Kita akan membuat 3 widget (activity) sebagai bagian dari route. Pertama kita akan membuat HomeActivity. Pada widget ini kita hanya menampilkan tulisan “Home screen” dan button detail.
import 'package:explore_data/pageRoutes.dart';
import 'package:flutter/material.dart';
class HomeActivity extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
Align(
alignment: Alignment.center,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
margin: EdgeInsets.only(bottom: 12),
child: Text("Home screen"),
),
RaisedButton(
onPressed: () {
///Navigasi
Navigator.of(context).pushNamed(PageRoutes.linkDetail);
},
child: Text("Detail"),
)
],
),
)
],
));
}
}
- StatelessWidget digunakan karena pada screen ini kita hanya akan menampilkan text, tanpa melakukan perubahan UI apapun secara dinamis
- Penjelasan terkait widget Stack, bisa teman-teman baca pada artikel ini ya “Mengelompokkan Berbagai Widget dengan Stack“
- Penjelasan terkait widget Column, bisa teman-teman baca pada artikel ini ya “Mengelompokkan Berbagai Widget dengan Column“
- Navigasi ke halaman detail dilakukan dengan Navigator.of(context).pushNamed(PageRoutes.linkDetail);
Selanjutnya ke DetailActivity. Pada widget ini kita menampilkan text yang dapat berubah secara dinamis, button untuk navigasi kembali ke widget sebelumnya, dan juga button untuk navigasi ke widget SubDetailActivity
import 'package:explore_data/pageRoutes.dart';
import 'package:flutter/material.dart';
class DetailActivity extends StatefulWidget {
@override
State<StatefulWidget> createState() => DetailActivityState();
}
class DetailActivityState extends State<DetailActivity> {
String text = "DetailActivity: 100";
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
Align(
alignment: Alignment.center,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
margin: EdgeInsets.only(bottom: 12),
child: Text(text),
),
RaisedButton(
onPressed: () {
///Navigasi
Navigator.of(context).pop();
},
child: Text("Kembali"),
),
RaisedButton(
onPressed: () {
_onClickSubDetail();
},
child: Text("Sub Detail"),
)
],
),
)
],
));
}
///Navigasi
_onClickSubDetail() async {
var returnValue = await Navigator.of(context).pushNamed(
PageRoutes.linkSubDetail,
arguments: {PageRoutes.param1: "DetailActivity: 100"});
if (returnValue != null)
setState(() {
text = returnValue;
});
}
}
- StatefulWidget digunakan karena pada screen ini kita akan mengubah tampilan text secara dinamis, ketika SubDetailActivity memberikan nilai kembali ke DetailActivity
- Navigator.of(context).pop(); digunakan untuk navigasi kembali ke widget sebelumnya. (Warning: Layar hitam akan muncul jika code ini digunakan, dan tidak ada widget yang ditumpuk pada route)
- Navigasi ke PageRoutes.linkSubDetail dilakukan dengan menambahkan argumen. Sesuai dengan schema kita pada awal tulisan ini, yaitu membawa data ke halaman Sub Detail
- Navigasi PageRoutes.linkSubDetail ditambahkan await di depannya, karena widget DetailActivity menunggu nilai kembali dari SubDetailActivity. Karena penggunaan await, function _onClickSubDetail() harus ditambahkan async karena function berjalan secara asynchronous.
Selanjutnya ke SubDetailActivity. Pada halaman ini kita menampilkan text dengan nilai dari DetailActivity.dart, text keterangan, dan juga button untuk navigasi kembali ke widget sebelumnya
import 'package:flutter/material.dart';
class SubDetailActivity extends StatelessWidget {
final String text;
SubDetailActivity(this.text);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
Align(
alignment: Alignment.center,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
margin: EdgeInsets.only(bottom: 12),
child: Text("$text"),
),
Text("Klik kembali untuk mengirim nilai 85 ke DetailActivity"),
RaisedButton(
onPressed: () {
///Navigasi
Navigator.of(context).pop("SubDetailActivity: 85");
},
child: Text("Kembali"),
),
],
),
)
],
));
}
}
- Navigasi ke halaman sebelumnya dengan memberikan nilai dapat dilakukan dengan menambahkan argumen di dalam method pop
- Dengan code di atas kita memberikan nilai kembali “SubDetailActivity: 85” ke widget sebelumnya
4. main.dart
Setelah widget dibuat beserta navigasinya, aplikasi masih belum berjalan sesuai dengan schema yang kita inginkan. Hal ini terjadi karena kita belum mengatur Route pada main.dart. Perbaru main.dart menjadi seperti berikut:
import 'package:explore_data/pageRoutes.dart';
import 'package:explore_data/useCase/DetailActivity.dart';
import 'package:explore_data/useCase/HomeActivity.dart';
import 'package:explore_data/useCase/SubDetailActivity.dart';
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
onGenerateRoute: _getRoute,
);
}
}
Route _getRoute(RouteSettings settings) {
final Map<String, dynamic> arguments = settings.arguments;
switch (settings.name) {
case PageRoutes.linkHome:
return CustomPageRoute(page: HomeActivity());
case PageRoutes.linkDetail:
return CustomPageRoute(
page: DetailActivity());
case PageRoutes.linkSubDetail:
return CustomPageRoute(
page: SubDetailActivity(arguments[PageRoutes.param1]));
}
return CustomPageRoute(page: HomeActivity());
}
- Pada MaterialApp kita menambahkan onGenerateRoute untuk mengatur semua route pada aplikasi
- Pada function _getRoute, kita menentukan Widget tujuan dengan nama dari class PageRoutes.
Dan sekarang, aplikasi telah berjalan sesuai dengan schema yang kita inginkan. Selamat, kita telah menerapkan navigation dan routing di aplikasi Flutter 😀
#etc
pushNamed pada Navigator akan menumpuk screen sekarang di belakang screen tujuan. Sehingga jika di pop, maka screen sebelumnya akan muncul kembali.
Jika ingin berpindah ke screen baru, tapi menghapus semua route dari widget sebelumnya (jika diback atau dipop widget sebelumnya gk akan muncul), gunakan code berikut ini:
// Tanpa argument
Navigator.of(context).pushNamedAndRemoveUntil(link, (Route<dynamic> route) => false);
// Dengan argument
Navigator.of(context).pushNamedAndRemoveUntil(link, (Route<dynamic> route) => false, arguments: arguments);
#Extra
Flutter memiliki update terkait navigation dan routing yaitu Navigator 2.0. Lalu mana yang lebih bagus digunakan?
“Note that this new mechanism (Navigator 2.0) isn’t a breaking change—you can continue to use the original approach if that serves you well. If you want to implement deep linking, or take advantage of multiple navigators, check out the 2.0 version.” (sumber)
Kita akan bahas Navigator 2.0 pada tulisan lainnya ya, sekian dulu tulisan kali ini, terimakasih.
Oh iya di website ini ada tulisan menarik lainnya juga loh, seperti berikut: