지난 포스팅에서 화면 전환에 대한 언급을 살짝 한 것 같은데, 어찌 됐든 거의 대부분의 앱은 여러 화면 구성을 가진다. 그리고 그 화면 간 전환도 필수적인 요소이다. 오늘은 여러 화면 전환 방법과 약간의 커스텀이 들어간 화면 전환 방식을 알아보자.
스크린 별로 UI 레이아웃을 관리해 주기 위해 따로 파일을 구성하였다. 화면끼리 연결해 주기 위해 연결될 화면의 경로를 통해 항상 import 해줄 필요가 있다.
Navigator.push()
// home_screen.dart
import 'package:flutter/cupertino.dart';
import 'package:sample_screen_change/screen/next_screen.dart';
/*
전체 코드 생략
*/
Navigator.push(
context,
CupertinoPageRoute(
fullscreenDialog: false, // true라면 모달 스타일로 화면 전환
builder: (context) => const NextScreen(),
),
);
// next_screen.dart
import 'package:flutter/cupertino.dart';
/*
전체 코드 생략
*/
Navigator.pop(context); // 이전 화면으로 돌아감
먼저 가장 기본적인 화면 전환 방법이다. home_screen.dart에서 next_screen으로 넘어가야 하므로 홈 화면 파트에 next_screen.dart를 import 해주었다. Navigation.push() 메서드를 통해 HomeScreen()에서 NextScreen()으로의 화면 전환이 가능하다.
플러터에서는 Cupertino Design 기준으로 세 가지 방식의 화면 전환이 제공된다. 앞선 두 가지 방식은 fullscreenDialog의 여부로 설정할 수 있는데, false라면 화면 오른쪽에서 왼쪽으로, true라면 아래서 위로 연결된 화면이 등장한다. 이 두가지 방식은 원래 화면 위에 스택을 쌓는 방식이므로 기존의 화면이 우리 눈에 보이진 않지만 남아 있는 상태이다. 따라서 원래 화면으로 돌아가고 싶으면 현재 화면을 Navigator.pop() 메서드를 통해 없애줄 수 있다.
Navigator.pushReplacement()
// home_screen.dart
Navigator.pushReplacement(
context,
CupertinoPageRoute(
builder: (context) => NextScreen()),
);
// next_screen.dart
Navigator.pushReplacement(
context,
CupertinoPageRoute(
builder: (context) => HomeScreen()),
);
다음은 replacement 방식이다. 이걸 이용하면 기존의 화면을 다른 화면으로 대체한다. 따라서 연결된 화면에서도 원래 화면으로 돌아오려면 다시 replacement를 사용해야 한다. Navigator.pop() 메서드를 무턱대고 써버리면 원래 화면이 남아있지 않기 때문에 화면에 아무것도 표시되지 않거나 기존에 남아 있던 엉뚱한 화면이 남을 수 있다.
showCupertinoModalPopup()
/*
기존 코드 생략
*/
showCupertinoModalPopup(
context: context,
builder: (BuildContext context) {
return _buildModalSheet(context);
},
);
/*
기존 코드 생략
*/
Widget _buildModalSheet(BuildContext context) {
return FractionallySizedBox(
heightFactor: 0.9, // 화면의 90% 를 차지하도록 설정
child: CupertinoPopupSurface(
child: CupertinoPageScaffold(
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Text('This is a fractional modal sheet'),
CupertinoButton(
child: const Text('Close'),
onPressed: () {
Navigator.pop(context);
},
),
],
),
),
),
),
);
}
추가적으로, 화면 전환은 아니지만 팝업 스크린 위젯을 활용하는 방법이다. 위젯이므로 같은 클래스 내에 작성해 주어야 한다. FractionallySizedBox로 화면 사이즈를 비율적으로 가져와서 그 위에 페이지를 구성한다. iOS 13에서부터 등장했던 화면 대부분을 덮는 모달 방식은 플러터 자체로 구현이 힘들어 이렇게 커스텀을 해주는 방식을 이용해 보았다.
전체 코드 보기
각각의 방식 별로 코드를 작성 후 주석 처리를 해두었다. 원하는 방식에 맞게 주석을 풀어 실행시키면 된다.
// main.dart
import 'package:flutter/cupertino.dart';
import 'package:sample_screen_change/screen/home_screen.dart';
void main() {
runApp(
const CupertinoApp(
home: HomeScreen()
)
);
}
// home_screen.dart
import 'package:flutter/cupertino.dart';
import 'package:sample_screen_change/screen/next_screen.dart';
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
navigationBar: const CupertinoNavigationBar(
middle: Text('Home Screen'),
),
child: Center(
child: CupertinoButton(
child: const Text('Show Modal'),
onPressed: () {
// 1, 2. push
Navigator.push(
context,
CupertinoPageRoute(
fullscreenDialog: false, // 모달 스타일로 화면 전환
builder: (context) => const NextScreen(),
),
);
// // 3. replacement
// Navigator.pushReplacement(
// context,
// CupertinoPageRoute(
// builder: (context) => const NextScreen()),
// );
// // 4. fractional modal
// showCupertinoModalPopup(
// context: context,
// builder: (BuildContext context) {
// return _buildModalSheet(context);
// },
// );
},
),
),
);
}
Widget _buildModalSheet(BuildContext context) {
return FractionallySizedBox(
heightFactor: 0.9, // 화면의 90% 를 차지하도록 설정
child: CupertinoPopupSurface(
child: CupertinoPageScaffold(
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Text('This is a fractional modal sheet'),
CupertinoButton(
child: const Text('Close'),
onPressed: () {
Navigator.pop(context);
},
),
],
),
),
),
),
);
}
}
// next_screen.dart
import 'package:flutter/cupertino.dart';
import 'package:sample_screen_change/screen/home_screen.dart';
class NextScreen extends StatelessWidget {
const NextScreen({super.key});
@override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: const Text('Next Screen'),
leading: CupertinoButton(
padding: EdgeInsets.zero,
child: const Icon(CupertinoIcons.back),
onPressed: () {
// 1, 2. push
Navigator.pop(context);
// // 3. replacement
// Navigator.pushReplacement(
// context,
// CupertinoPageRoute(
// builder: (context) => HomeScreen()),
// );
},
),
),
child: const Center(
child: Text('This is the Next Screen'),
),
);
}
}
화면만 옮기면 뭐 해, 화면에 따라 데이터를 주고받을 수 있어야지. 그렇다. 다음 포스팅은 화면 간에 데이터를 옮기는 실습을 지금 예제 코드 위에 입혀 보겠다.
'Dev > flutter' 카테고리의 다른 글
[Dev, flutter] 플러터로 iOS 앱 개발 시작하기 (8) - 앱 아이콘, 런치 스크린 (4) | 2024.09.03 |
---|---|
[Dev, flutter] 플러터로 iOS 앱 개발 시작하기 (6) - PageView (2) | 2024.08.09 |
[Dev, flutter] 플러터로 iOS 앱 개발 시작하기 (5) - STT, TTS (2) | 2024.08.08 |
[Dev, flutter] 플러터로 iOS 앱 개발 시작하기 (4) - 서버에 이미지 업로드 (2) | 2024.08.06 |
[Dev, flutter] 플러터로 iOS 앱 개발 시작하기 (3) - Camera, Gallery (2) | 2024.08.05 |