Navigation 1.0
Pemrograman Mobile
Muhamad Saad Nurul Ishlah, M.Comp.
Dept. Sistem Informasi & Dept. Ilmu Komputer, Universitas Pakuan
@optionalTypeArgs
Future<T?> push<T extends Object?>(
BuildContext context,
Route<T> route
)
@optionalTypeArgs
class FirstRoute extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('First Route'),
),
body: Center(
child: ElevatedButton(
child: Text('Open route'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondRoute()),
);
},
),
),
);
}
}
class SecondRoute extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Second Route"),
),
body: Center(
child: ElevatedButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('Go back!'),
),
),
);
}
}
Pindah ke layar baru (SecondRoute)
Kembali ke layar sebelumnya (FirstRoute)
(Named Routes)
anonymous routes – duplikasi kode
@optionalTypeArgs
Future<T?> pushNamed <T extends Object?>(
BuildContext context,
String routeName,
{Object? arguments}
)
@optionalTypeArgs
import 'package:flutter/material.dart';
void main() {
runApp(
MaterialApp(
title: 'Named Routes Demo',
// Start the app with the "/" named route. In this case, the app starts
// on the FirstScreen widget.
initialRoute: '/',
routes: {
// When navigating to the "/" route, build the FirstScreen widget.
'/': (context) => FirstScreen(),
// When navigating to the "/second" route, build the SecondScreen widget.
'/second': (context) => SecondScreen(),
},
),
);
}
class FirstScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('First Screen'),
),
body: Center(
child: ElevatedButton(
// Within the `FirstScreen` widget
onPressed: () {
// Navigate to the second screen using a named route.
Navigator.pushNamed(context, '/second');
},
child: Text('Launch screen'),
),
),
);
}
}
class SecondScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Second Screen"),
),
body: Center(
child: ElevatedButton(
// Within the SecondScreen widget
onPressed: () {
// Navigate back to the first screen by popping the current route
// off the stack.
Navigator.pop(context);
},
child: Text('Go back!'),
),
),
);
}
}
Menggunakan Named Routes
import 'package:flutter/material.dart';
void main() {
runApp(
MaterialApp(
title: 'Named Routes Demo',
// Start the app with the "/" named route. In this case, the app starts
// on the FirstScreen widget.
initialRoute: '/',
routes: {
// When navigating to the "/" route, build the FirstScreen widget.
'/': (context) => FirstScreen(),
// When navigating to the "/second" route, build the SecondScreen widget.
'/second': (context) => SecondScreen(),
},
),
);
}
class FirstScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('First Screen'),
),
body: Center(
child: ElevatedButton(
// Within the `FirstScreen` widget
onPressed: () {
// Navigate to the second screen using a named route.
Navigator.pushNamed(context, '/second');
},
child: Text('Launch screen'),
),
),
);
}
}
class SecondScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Second Screen"),
),
body: Center(
child: ElevatedButton(
// Within the SecondScreen widget
onPressed: () {
// Navigate back to the first screen by popping the current route
// off the stack.
Navigator.pop(context);
},
child: Text('Go back!'),
),
),
);
}
}
Kembali ke layar pertama
Peringatan:
Saat menggunakan initialRoute, jangan tentukan properti home.
@optionalTypeArgs
Future<T?> pushNamed <T extends Object?>(
BuildContext context,
String routeName,
{Object? arguments}
)
@optionalTypeArgs
// You can pass any object to the arguments parameter.
// In this example, create a class that contains both
// a customizable title and message.
class ScreenArguments {
final String title;
final String message;
ScreenArguments(this.title, this.message);
}
// A Widget that extracts the necessary arguments from
// the ModalRoute.
class ExtractArgumentsScreen extends StatelessWidget {
static const routeName = '/extractArguments';
@override
Widget build(BuildContext context) {
// Extract the arguments from the current ModalRoute
// settings and cast them as ScreenArguments.
final ScreenArguments args =
ModalRoute.of(context)!.settings.arguments as ScreenArguments;
return Scaffold(
appBar: AppBar(
title: Text(args.title),
),
body: Center(
child: Text(args.message),
),
);
}
}
// Register the widget in the routes
MaterialApp(
routes: {
ExtractArgumentsScreen.routeName: (context) => ExtractArgumentsScreen(),
},
)
// A button that navigates to a named route.
// The named route extracts the arguments
// by itself.
ElevatedButton(
child: Text("Navigate to screen that extracts arguments"),
onPressed: () {
// When the user taps the button,
// navigate to a named route and
// provide the arguments as an optional
// parameter.
Navigator.pushNamed(
context,
ExtractArgumentsScreen.routeName,
arguments: ScreenArguments(
'Extract Arguments Screen',
'This message is extracted in the build method.',
),
);
},
),
Langkah-langkah
MaterialApp(
// Provide a function to handle named routes.
// Use this function to identify the named
// route being pushed, and create the correct
// Screen.
onGenerateRoute: (settings) {
// If you push the PassArguments route
if (settings.name == PassArgumentsScreen.routeName) {
// Cast the arguments to the correct
// type: ScreenArguments.
final ScreenArguments args = settings.arguments as ScreenArguments;
// Then, extract the required data from
// the arguments and pass the data to the
// correct screen.
return MaterialPageRoute(
builder: (context) {
return PassArgumentsScreen(
title: args.title,
message: args.message,
);
},
);
}
// The code only supports
// PassArgumentsScreen.routeName right now.
// Other values need to be implemented if we
// add them. The assertion here will help remind
// us of that higher up in the call stack, since
// this assertion would otherwise fire somewhere
// in the framework.
assert(false, 'Need to implement ${settings.name}');
return null;
},
)
Daripada mengesktrak langsung di widget, argumen dapat diekstrak dengan menggunakan fungsi onGenerateRoute() dan meneruskannya ke widget
@optionalTypeArgs
void pop <T extends Object?>(
BuildContext context,
[T? result]
)
@optionalTypeArgs
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Returning Data Demo'),
),
// Create the SelectionButton widget in the next step.
body: Center(child: SelectionButton()),
);
}
}
class SelectionButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () {
_navigateAndDisplaySelection(context);
},
child: Text('Pick an option, any option!'),
);
}
// A method that launches the SelectionScreen and awaits the
// result from Navigator.pop.
_navigateAndDisplaySelection(BuildContext context) async {
// Navigator.push returns a Future that completes after calling
// Navigator.pop on the Selection Screen.
final result = await Navigator.push(
context,
// Create the SelectionScreen in the next step.
MaterialPageRoute(builder: (context) => SelectionScreen()),
);
// After the Selection Screen returns a result, hide any previous snackbars
// and show the new result.
ScaffoldMessenger.of(context)
..removeCurrentSnackBar()
..showSnackBar(SnackBar(content: Text("$result")));
}
}
class SelectionScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Pick an option'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: ElevatedButton(
onPressed: () {
// The Yep button returns "Yep!" as the result.
Navigator.pop(context, 'Yep!');
},
child: Text('Yep!'),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: ElevatedButton(
onPressed: () {
// The Nope button returns "Nope!" as the result.
Navigator.pop(context, 'Nope!');
},
child: Text('Nope.'),
),
)
],
),
),
);
}
}
Langkah-langkah:
https://gist.github.com/nurulishlah/0b9239de66a366cb60e0500224da421d