import 'package:flutter/material.dart';
import 'package:navigation/screen/route_one_screen.dart';
class HomeScreen extends StatelessWidget {
const HomeScreen({Key? key}) : super(key: key);
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Home Screen'),
),
body: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
ElevatedButton(
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) => RouteOneScreen(),
),
);
},
child: const Text('Push')),
],
),
),
);
}
}
Navigator.of(context)
는 위젯트리에서 가장 가까운 Navigator를 가져다주는 역할을 한다.MaterialPageRoute
를 사용하고 builder
함수에는 새로운 페이지에 해당하는 위젯을 리턴해주면 된다.import 'package:flutter/material.dart';
class RouteOneScreen extends StatelessWidget {
const RouteOneScreen({Key? key}) : super(key: key);
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Route One'),
),
body: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
ElevatedButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text('Pop'),
),
],
),
),
);
}
}
Navigator.of(context)
에 pop()
메서드를 사용하면 된다.import 'package:flutter/material.dart';
class MainLayout extends StatelessWidget {
final String title;
final List<Widget> children;
변경되는 값은 appbar에 title값과 ElevatedButton이기 때문에 변수로 만들어 관리해준다.
const MainLayout({
required this.title,
required this.children,
Key? key,
}) : super(key: key);
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: children,
),
),
);
}
}
기본적으로 값을 넘겨줄 때는 변수를 선언해서 넘겨준다.
값을 받을 페이지에 number라는 변수를 만들고 HomeScreen에서 그 값을 입력해준다.
값을 돌려받을 때는 pop()에 돌려 받을 값을 넣고 HomeScreen에 onPressed 함수를 async로 바꾸어주면 된다.
--- RouteOneScreen ---
import 'package:flutter/material.dart';
import 'package:navigation/layout/main_layout.dart';
class RouteOneScreen extends StatelessWidget {
final int number;
const RouteOneScreen({
required this.number,
Key? key,
}) : super(key: key);
Widget build(BuildContext context) {
return MainLayout(
title: 'Route One',
children: [
Text(
number.toString(),
textAlign: TextAlign.center,
),
ElevatedButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text('Pop'),
),
],
);
}
}
--- HomeScreen ---
import 'package:flutter/material.dart';
import 'package:navigation/layout/main_layout.dart';
import 'package:navigation/screen/route_one_screen.dart';
class HomeScreen extends StatelessWidget {
const HomeScreen({Key? key}) : super(key: key);
Widget build(BuildContext context) {
return MainLayout(
title: 'Home Screen',
children: [
ElevatedButton(
onPressed: () async {
final result = await Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) => RouteOneScreen(
number: 123,
),
),
);
print(result);
},
child: const Text('Push'),
),
],
);
}
}
class RouteOneScreen extends StatelessWidget {
final int number;
const RouteOneScreen({
required this.number,
Key? key,
}) : super(key: key);
Widget build(BuildContext context) {
return MainLayout(
title: 'Route One',
children: [
Text(
number.toString(),
textAlign: TextAlign.center,
),
ElevatedButton(
onPressed: () {
Navigator.of(context).pop(456);
},
child: const Text('Pop'),
),
ElevatedButton(
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => RouteTwoScreen(),
settings: RouteSettings(
arguments: 789,
),
),
);
},
child: Text('Push'),
)
],
);
}
}
ModalRoute
를 사용하여 값을 받는다.class RouteTwoScreen extends StatelessWidget {
const RouteTwoScreen({Key? key}) : super(key: key);
Widget build(BuildContext context) {
final arguments = ModalRoute.of(context)!.settings.arguments;
return MainLayout(
title: 'Route Two',
children: [
Text(
'arguments : ${arguments}',
textAlign: TextAlign.center,
),
ElevatedButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text('Pop'),
),
],
);
}
}
'/'
, '/one'
이런 형태로 작성했다.--- HomeScreen ---
void main() {
runApp(
MaterialApp(
//home: HomeScreen(),
initialRoute: '/',
routes: {
'/': (context) => HomeScreen(),
'/one': (context) => RouteOneScreen(),
'/two': (context) => RouteTwoScreen(),
'/three': (context) => RouteThreeScreen(),
},
),
);
}
--- RouteTwoScreen ---
ElevatedButton(
onPressed: () {
Navigator.of(context).pushNamed(
'/three',
arguments: 999,
);
},
child: Text('Push Named'),
)
--- RouteThreeScreen ---
class RouteThreeScreen extends StatelessWidget {
const RouteThreeScreen({Key? key}) : super(key: key);
Widget build(BuildContext context) {
final arguments = ModalRoute.of(context)!.settings.arguments;
return MainLayout(
title: 'Route Three',
children: [
Text(
'arguments : ${arguments}',
textAlign: TextAlign.center,
),
ElevatedButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text('Pop')),
],
);
}
}
--- RouteTwoScreen ---
ElevatedButton(
onPressed: () {
Navigator.of(context).pushReplacement(
MaterialPageRoute(
builder: (_) => RouteThreeScreen(),
),
);
},
child: Text('Push Replacement'),
)
Push Replacement
버튼을 누르고 RouteThree로 이동했다. RouteThree에서 pop버튼을 눌러 뒤로가기를 했더니 RouteOne 페이지로 이동하였다.[HomeScreen, RouteOneScreen, RouteTwoScreen]
에서 push를 하면[HomeScreen, RouteOneScreen, RouteTwoScreen, RouteThreeScreen]
이렇게 페이지가 쌓이고 pop()을 하면 RouteThreeScreen
이 사라지면서[HomeScreen, RouteOneScreen, RouteTwoScreen]
순서로 바뀐다.pushReplacement
메소드를 사용하면 [HomeScreen, RouteOneScreen, RouteTwoScreen]
에서 RouteTwoScreen
가 RouteThreeScreen
로 대체되서 [HomeScreen, RouteOneScreen, RouteThreeScreen]
가 된다. 그래서 RouteThreeScreen
에서 pop을 하면 RouteOneScreen
이 출력되게 된다.pushReplacement
는 push와 마찬가지로 Named Route를 사용할 수 있다.--- RouteTwoScreen ---
ElevatedButton(
onPressed: () {
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(
builder: (_) => RouteThreeScreen(),
),
(route) => false);
},
child: Text('Push And Remove Until'),
)
RouteTwoScreen
에서 pushAndRemoveUntil
메소드를 사용하여 버튼을 만들었다.pushAndRemoveUntil
은 라우트를 설정할 수 있는데, 만약 라우트에 false를 설정하고 버튼을 눌러 RouteThreeScreen
에 이동하게 되면 나머지 페이지들이 삭제가 된다. ElevatedButton(
onPressed: () {
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(
builder: (_) => RouteThreeScreen(),
),
(route) => route.settings.name == '/');
},
child: Text('Push And Remove Until'),
)
ElevatedButton(
onPressed: () {
Navigator.of(context).maybePop();
},
child: Text('Maybe Pop'),
),
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
// true - pop 가능
// false - pop 불가능
return false;
},
child: MainLayout(
title: 'Home Screen',
children: [.....]
)