Navigator Push
1. Navigator.push()로 화면 전환
전달할 데이터가 없는 경우에는 Navigator.push()
메소드를 통해 화면전환을 할 수 있습니다.
Navigator.push()
에 전환할 페이지를 MaterialPageRoute()에 넣어주면 됩니다.
Navigator.push(context, MaterialPageRoute(builder: (context) => FirstScreen()));
main.dart
import 'package:flutter/material.dart';
import 'package:flutter_widgets/screen/button_above_keyboard.dart';
import 'package:flutter_widgets/screen/first_screen.dart';
import 'package:flutter_widgets/screen/second_screen.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Widgets',
theme: ThemeData(
primaryColor: Colors.blue,
brightness: Brightness.dark),
home: new HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(
title: Text("Flutter Widgets"),
),
body: Container(
child: Column(
children: [
Expanded(
child: ListView(
children: [
ListTile(
title: Text('FirstScreen'),
onTap: () {
// 화면전환(데이터 전달x)
Navigator.push(context, MaterialPageRoute(builder: (context) => FirstScreen()));
},
),
],
),
)
],
),
),
);
}
}
first_screen.dart
import 'package:flutter/material.dart';
import 'package:flutter_widgets/text_style.dart';
class FirstScreen extends StatefulWidget {
@override
_FirstScreenState createState() => _FirstScreenState();
}
class _FirstScreenState extends State<FirstScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
'FirstScreen',
style: kNotoSansMedium16.copyWith(color: Colors.white),
),
),
);
}
}
2. Navigator.pushNamed()를 통한 화면전환
MaterialApp의 속성인 initialRoute와 routes를 통해 경로를 제공할 수 있습니다.
initialRoute는 앱의 시작화면을 지정할 수 있고,
routes에 ScreenName과 Widget을 Map으로 만들어 지정하면 String을 통해 Navigator.pushNamed()
를 통해 간단하게 화면전환을 할 수 있습니다.
MaterialApp(
title: 'Flutter Widgets',
theme: ThemeData(
primaryColor: Colors.blue,
brightness: Brightness.dark),
initialRoute: HomeScreen.routeName,
routes: routes
)
final routes = {
HomeScreen.routeName: (context) => HomeScreen(),
SecondScreen.routeName: (context) => SecondScreen(),
};
Navigator.pushNamed(context, SecondScreen.routeName);
혹은 routes를 MaterialApp에서 지정하지 않고 화면전환을 하려면 아래와 같이 사용하면 됩니다.
Navigator.push(
context,
MaterialPageRoute(
settings: const RouteSettings(name: SecondScreen.routeName),
builder: (context) => SecondScreen(),
));
main.dart
import 'package:flutter/material.dart';
import 'package:flutter_widgets/screen/button_above_keyboard.dart';
import 'package:flutter_widgets/screen/first_screen.dart';
import 'package:flutter_widgets/screen/second_screen.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Widgets',
theme: ThemeData(
primaryColor: Colors.blue,
brightness: Brightness.dark),
routes: routes,
home: new HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(
title: Text("Flutter Widgets"),
),
body: Container(
child: Column(
children: [
Expanded(
child: ListView(
children: [
ListTile(
title: Text('SecondScreen'),
onTap: () {
// Navigator.pushNamed()를 통한 화면전환
Navigator.pushNamed(
context,
SecondScreen.routeName,
);
},
),
],
),
)
],
),
),
);
}
}
final routes = {
HomeScreen.routeName: (context) => HomeScreen(),
SecondScreen.routeName: (context) => SecondScreen(),
};
second_screen.dart
import 'package:flutter/material.dart';
import 'package:flutter_widgets/text_style.dart';
class SecondScreen extends StatefulWidget {
static String routeName = "/second_screen";
@override
_SecondScreenState createState() => _SecondScreenState();
}
class _SecondScreenState extends State<SecondScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
'SecondScreen',
style: kNotoSansMedium16.copyWith(color: Colors.white),
),
),
);
}
}
3. Navigator.push(), Navigator.pushNamed()를 통한 화면전환 with Arguments(데이터 전달)
3 - (1) Navigator.push()를 통한 데이터 전달
Navigator.push()
에 MaterialPageRoute인자를 이용하여 데이터를 전달할 수 있습니다.
Navigator.push(context, MaterialPageRoute(builder: (context) => ThirdScreen(update: true)));
main.dart
import 'package:flutter/material.dart';
import 'package:flutter_widgets/screen/button_above_keyboard.dart';
import 'package:flutter_widgets/screen/first_screen.dart';
import 'package:flutter_widgets/screen/second_screen.dart';
import 'package:flutter_widgets/screen/third_screen.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Widgets',
theme: ThemeData(primaryColor: Colors.blue, brightness: Brightness.dark),
initialRoute: HomeScreen.routeName,
routes: routes,
);
}
}
class HomeScreen extends StatelessWidget {
static String routeName = "/";
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(
title: Text("Flutter Widgets"),
),
body: Container(
child: Column(
children: [
Expanded(
child: ListView(
children: [
ListTile(
title: Text('ThirdScreen'),
onTap: () {
Navigator.push(context, MaterialPageRoute(builder: (context) => ThirdScreen(update: true)));
},
),
],
),
)
],
),
),
);
}
}
third_screen.dart
import 'package:flutter/material.dart';
import 'package:flutter_widgets/text_style.dart';
class ThirdScreen extends StatefulWidget {
const ThirdScreen({required this.update, Key? key}) : super(key: key);
final bool update;
static const String routeName = "/third_screen";
@override
_ThirdScreenState createState() => _ThirdScreenState();
}
class _ThirdScreenState extends State<ThirdScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
'ThirdScreen',
style: kNotoSansMedium16.copyWith(color: Colors.white),
),
),
body: SafeArea(
child: Column(
children: [
Spacer(),
Center(
child: Text(
'${widget.update}',
style: kNotoSansMedium16.copyWith(color: Colors.white),
),
),
Spacer(),
],
),
),
);
}
}
3 - (2) Navigator.pushNamed()를 통한 데이터 전달
routeName과 데이터를 포함하는 MaterialPageRoute를 사용하려면 Map을 통해 MaterialApp의 onGenerateRoute를 통해 제공해야 합니다.
여기에 Map을 통해 데이터를 넣어주면, Navigator.pushNamed()
를 통해 화면전환을 할 수 있습니다.
MaterialApp(
title: 'Flutter Widgets',
theme: ThemeData(
primaryColor: Colors.blue,
brightness: Brightness.dark),
initialRoute: HomeScreen.routeName,
onGenerateRoute: generateRoute,
routes: routes,
);
}
Route? generateRoute(RouteSettings routeSettings) {
switch (routeSettings.name) {
case ThirdScreen.routeName:
return MaterialPageRoute(
builder: (context) {
var map = routeSettings.arguments as Map<String, dynamic>;
return ThirdScreen(
update: map['update'] as bool,
);
},
settings: routeSettings,
);
default:
return null;
}
}
import 'package:flutter/material.dart';
import 'package:flutter_widgets/screen/button_above_keyboard.dart';
import 'package:flutter_widgets/screen/first_screen.dart';
import 'package:flutter_widgets/screen/second_screen.dart';
import 'package:flutter_widgets/screen/third_screen.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Widgets',
theme: ThemeData(
primaryColor: Colors.blue,
brightness: Brightness.dark),
initialRoute: HomeScreen.routeName,
onGenerateRoute: generateRoute,
routes: routes,
);
}
Route? generateRoute(RouteSettings routeSettings) {
switch (routeSettings.name) {
case ThirdScreen.routeName:
return MaterialPageRoute(
builder: (context) {
var map = routeSettings.arguments as Map<String, dynamic>;
return ThirdScreen(
update: map['update'] as bool,
);
},
settings: routeSettings,
);
default:
return null;
}
}
}
class HomeScreen extends StatelessWidget {
static String routeName = "/";
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(
title: Text("Flutter Widgets"),
),
body: Container(
child: Column(
children: [
Expanded(
child: ListView(
children: [
ListTile(
title: Text('ThirdScreen'),
onTap: () {
// 화면전환
Navigator.pushNamed(context, ThirdScreen.routeName, arguments: {"update": true});
},
),
],
),
)
],
),
),
);
}
}
4. Navigator.pushNamedAndRemoveUntil()을 이용한 화면전환
Navigator.pushNamedAndRemoveUntil()
를 이용하면 페이지를 push()함과 동시에 Stack에 쌓여있던 페이지들을 제거할 수 있습니다.
Navigator.pushNamedAndRemoveUntil(context, newRouteName, (route) => false);
예시)
이전 스택 페이지들 전부 제거
Navigator.pushNamedAndRemoveUntil(context, ThirdScreen.routeName, (route) => false, arguments: {"update": true});
스택의 특정 페이지 이전까지 모두 제거
Navigator.pushNamedAndRemoveUntil(context, ThirdScreen.routeName, ModalRoute.withName(SecondScreen.routeName), arguments: {"update": true});
second_screen.dart
import 'package:flutter/material.dart';
import 'package:flutter_widgets/main.dart';
import 'package:flutter_widgets/screen/third_screen.dart';
import 'package:flutter_widgets/text_style.dart';
class SecondScreen extends StatefulWidget {
static String routeName = "/second_screen";
@override
_SecondScreenState createState() => _SecondScreenState();
}
class _SecondScreenState extends State<SecondScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
'SecondScreen',
style: kNotoSansMedium16.copyWith(color: Colors.white),
),
),
body: SafeArea(
child: Column(
children: [
InkWell(
onTap: () {
Navigator.pushNamedAndRemoveUntil(context, ThirdScreen.routeName, ModalRoute.withName(SecondScreen.routeName), arguments: {"update": true});
},
child: Text(
"GoTo ThirdScreen",
style: kNotoSansMedium16.copyWith(color: Colors.white),
),
),
],
),
),
);
}
}
5. Navigator.pushReplacementNamed()를 통한 화면전환
Navigator.pushReplacementNamed()
를 이용하면 현재 페이지를 스택에서 제거하고 이동할 페이지를 스택에 집어넣을 수 있습니다.
Navigator.pushReplacementNamed(context, ThirdScreen.routeName);
간단하므로 예제는 생략하겠습니다.
Navigator Pop
1. Navigator.pop()
Navigator.pop()을 이용하면 현재 페이지를 스택에서 제거할 수 있습니다.
Navigator.pop(context);
예시)
third_screen.dart
import 'package:flutter/material.dart';
import 'package:flutter_widgets/text_style.dart';
class ThirdScreen extends StatefulWidget {
const ThirdScreen({required this.update, Key? key}) : super(key: key);
final bool update;
static const String routeName = "/third_screen";
@override
_ThirdScreenState createState() => _ThirdScreenState();
}
class _ThirdScreenState extends State<ThirdScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(Icons.arrow_back),
),
title: Text(
'ThirdScreen',
style: kNotoSansMedium16.copyWith(color: Colors.white),
),
),
);
}
}
2. Navigator.popUntil()
스택에 존재하는 페이지와 일치하는 페이지까지 스택에서 제거합니다.
Navigator.popUntil(context, ModalRoute.withName(HomeScreen.routeName));
예시)
third_screen.dart
import 'package:flutter/material.dart';
import 'package:flutter_widgets/main.dart';
import 'package:flutter_widgets/text_style.dart';
class ThirdScreen extends StatefulWidget {
const ThirdScreen({required this.update, Key? key}) : super(key: key);
final bool update;
static const String routeName = "/third_screen";
@override
_ThirdScreenState createState() => _ThirdScreenState();
}
class _ThirdScreenState extends State<ThirdScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
onPressed: () {
// Navigator.pop(context);
Navigator.popUntil(context, ModalRoute.withName(HomeScreen.routeName));
},
icon: Icon(Icons.arrow_back),
),
title: Text(
'ThirdScreen',
style: kNotoSansMedium16.copyWith(color: Colors.white),
),
),
body: SafeArea(
child: Column(
children: [
Spacer(),
Center(
child: Text(
'${widget.update}',
style: kNotoSansMedium16.copyWith(color: Colors.white),
),
),
Spacer(),
],
),
),
);
}
}
3. Navigator.popAndPushNamed()
현재 페이지를 스택에서 제거함과 동시에 새로운 페이지를 스택에 추가합니다.
Navigator.popAndPushNamed(context, SecondScreen.routeName);
예시)
third_screen.dart
import 'package:flutter/material.dart';
import 'package:flutter_widgets/main.dart';
import 'package:flutter_widgets/screen/first_screen.dart';
import 'package:flutter_widgets/screen/second_screen.dart';
import 'package:flutter_widgets/text_style.dart';
class ThirdScreen extends StatefulWidget {
const ThirdScreen({required this.update, Key? key}) : super(key: key);
final bool update;
static const String routeName = "/third_screen";
@override
_ThirdScreenState createState() => _ThirdScreenState();
}
class _ThirdScreenState extends State<ThirdScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
onPressed: () {
// Navigator.pop(context);
// Navigator.popUntil(context, ModalRoute.withName(HomeScreen.routeName));
Navigator.popAndPushNamed(context, SecondScreen.routeName);
},
icon: Icon(Icons.arrow_back),
),
title: Text(
'ThirdScreen',
style: kNotoSansMedium16.copyWith(color: Colors.white),
),
),
body: SafeArea(
child: Column(
children: [
Spacer(),
Center(
child: Text(
'${widget.update}',
style: kNotoSansMedium16.copyWith(color: Colors.white),
),
),
Spacer(),
],
),
),
);
}
}