우리는 웹/앱/애플리케이션을 사용할 때 화면이 전환되는 경험을 해본 적이 있습니다.
그러면 플러터에서 화면 전환을 하기 위해서는 어떤 방법을 사용해야할까요?
우선, 화면 전환에 대해 알기 전에 플러터에서 화면을 어떤 명칭으로 불리는 지 확인해봐야 합니다.
플러터 공식 문서에 따르면 플러터에서는 screen과 page는 route로 불린다고 합니다.
route은 flutter에서 위젯이며 Android의 Activity, iOS의 ViewController과 동일합니다.
그러면 새로운 route로 어떻게 이동할까요?
바로 Navigator를 사용하면 되는데요.
그러면 간단한 예제를 통해 새로운 화면으로 이동하고, 되돌아오는 방법에 대해 알아보겠습니다.
새로운 화면으로 이동하고, 되돌아오기
화면을 이동하기 위해서는 2개 이상의 화면이 필요합니다.
그래서 우선 화면 2개를 만들고 각 화면에는 화면을 이동할 수 있는 버튼을 생성하겠습니다.
- first_route.dart
import 'package:flutter/material.dart';
class FirstRoute extends StatelessWidget {
const FirstRoute({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('첫 번째 화면')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('첫 번째 화면 내용'),
ElevatedButton(
onPressed: () {},
child: const Text('두 번째 화면으로 이동'),
),
],
),
),
);
}
}
- second_route.dart
import 'package:flutter/material.dart';
class SecondRoute extends StatelessWidget {
const SecondRoute({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('두 번째 화면')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('두 번째 화면 내용'),
ElevatedButton(
onPressed: () {},
child: const Text('첫 번째 화면으로 이동'),
),
],
),
),
);
}
}
그러면 처음에 말했던 것처럼 화면을 이동하기 위해서는 Navigator를 사용해야 합니다.
Navigator는 스택 규칙을 사용하여 하위 위젯을 관리하는데, push는 Route를 Navigator에 의해 관리되는 route스택에 추가하고, pop는 route스택에서 현재 Route를 제거합니다.
그러면 FirstRoute화면에 생성된 버튼에 push() 메서드를 사용하고 SecondRoute 화면에 생성된 버튼에는 pop() 메서드를 사용해보겠습니다.
- first_route.dart
ElevatedButton(
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) => const SecondRoute(),
),
);
},
child: const Text('두 번째 화면으로 이동'),
),
- second_route.dart
ElevatedButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text('첫 번째 화면으로 이동'),
),
Navigator.of는 지정된 BuildContext에서 가장 가까운 상위 Navigator에서 작동하기 때문에,
현재 상위 위젯인 Scaffold에서 이동하겠다는 의미가 됩니다.
first_route.dart 소스를 보면 push() 메서드에서 추가할 Route를 직접 생성하거나 MaterialPageRoute를 사용해 이동할 페이지를 지정합니다.
MaterialPageRoute은 새로운 route 이동 시 플랫폼에 특화된 애니메이션으로 전환하는데,
Android의 경우 페이지의 시작 전환은 확대 및 페이드인, 나가는 페이지는 축소 및 페이드 아웃이 됩니다.
iOS의 경우 페이지가 오른쪽에서 슬라이드 안으로 들어갔다가 반대로 나오게 해 줍니다.
second_route.dart 소스를 보면. pop() 사용하여 현재 route를 닫고 이전 route로 되돌아가게 됩니다.
하지만, 앱의 다른 화면에서 동일한 화면으로 이동하고자 한다면, 중복된 코드가 생기게 됩니다.
그러면 natemed route를 정의하여 화면 전환에 사용하는 방법이 해결책이 될 수 있습니다.
Named route로의 화면 전환
Named route를 사용하기 위해 Navigator.pushNamed 메서드를 사용할 수 있습니다.
공식 문서를 보면 지정된 콘텍스트를 감싸는 Navigator에 지정한 경로를 푸시한다고 나와있습니다.
그렇다면 경로를 지정하려면 어떻게 해야 할까요?공식 문서에 따르면 MaterialApp을 다음 순서로 경로를 검색하도록 최상위 Navigator를 구성해야 한다고 나와 있습니다.
- /route에는 home 속성(null 이외의 경우)이 사용됩니다
- 다른 방법으로 route 진입로가 있는 경우 routes table이 사용된다.
- 그렇지 않으면 onGenerateRoute 가 호출됩니다.
만일 제공된다면 home 및 route에서 처리하지 않는 유효한 경로에 대해 null이 아닌 값을 반환해야 합니다. - 마지막으로 모든 것이 실패한 경우 onUnknownRoute이 호출됩니다.
그러면 MaterialApp생성자에 initialRoute와 routes로 route를 정의해보겠습니다.
initialRoute는 앱의 시작점을 나타내는 route를 정의하고, routes는 이용 가능한 named route와 해당 route로 이동했을 때 빌드된 위젯을 정의합니다.
그러면 시작 페이지는 FirstRoute로 정의하고 routes에는 FirstRoute와 SecondRoute를 정의해보겠습니다.
- main.dart
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(),
initialRoute: '/',
routes: {
'/': (context) => const FirstRoute(),
'/second': (context) => const SecondRoute(),
},
);
}
}
❗️공식문서에서 InitalRoute를 사용한다면, home는 정의하지 마세요라고 되어있습니다!
그러면 first_route.dart Navigator.push() 메서드를 Navigator.pushName() 메서드로 화면 전환을 해보겠습니다
ElevatedButton(
onPressed: () {
Navigator.pushNamed(context, '/second');
},
child: const Text('두 번째 화면으로 이동'),
),
이렇게 변경된 소스로 화면을 띄워보면 화면 이동이 잘 되는 것을 확인할 수 있습니다 😆
[참고]
https://flutter-ko.dev/docs/cookbook/navigation/navigation-basics
'IT > 기록' 카테고리의 다른 글
[Vue] Mac에서 Vue-Cli 설치하기 (0) | 2022.06.09 |
---|---|
[Flutter] 첫 앱 게시 삽질기 #1 잘 게시 되길 바라며 (0) | 2022.06.07 |
[JPA] Entity Validation - null (0) | 2022.05.31 |
[Flutter] ColorScheme class - 주요 색상만 지정하면 색깔을 알아서 뚝딱? (0) | 2022.05.20 |
Spring Data JPA 간단하게 알아보기 (0) | 2022.05.19 |