사진 여러 장을 좌우로 스와이프 하여 볼 수 있는 화면을 구성해 보자. 이번 예제는 너무 쉬워서 화면 구성에 관한 Tip과 심화 예제를 포함시킨다. 이번 실습은 <Must Have 코드팩토리의 플러터 프로그래밍 2판>을 참조하였다.
Assets
이미지 파일을 첨부하고, pubspec.yaml 파일을 업데이트해 주자.
스크린 나누기
import 'package:sample_swipe/screen/home_screen.dart';
import 'package:flutter/cupertino.dart';
void main() {
runApp(
const CupertinoApp(
home: HomeScreen(),
),
);
}
지금이야 화면 전환 없이 한 화면을 구성하는 것이 끝이지만, 현업에서나 토이 프로젝트를 진행하면 분명 여러 화면들이 필요할 것이다. 하지만 main.dart 파일 내에서 이 모든 화면을 구성한다면 가독성이 떨어지고 무거워질 것이다. 그래서 보통 스크린 별로 Dart 파일을 만들고, 각각에서 UI를 처리하는 방식이 일반적이다.
HomeScreen()은 이 앱의 진입점이 된다. main.dart에는 위 코드 외에 다른 코드가 없다. HomeScreen() 구성을 다른 파일에 해두었기에 파일끼리 linking을 위해 home_screen.dart 파일의 경로를 import 시켜주었다.
예를 들어 앱의 화면이 총 8개 필요하다면, sreen 디렉터리에 각 화면별로 8개의 파일을 구성하고, 이 파일들의 경로를 main.dart에 import 해주면 연결이 될 것이다.
1. PageView
import 'package:flutter/cupertino.dart';
class HomeScreen extends StatelessWidget {
const HomeScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
child: SafeArea(
child: PageView(
children: const [1, 2, 3, 4, 5].map(
(number) => Image.asset(
'assets/img/image_$number.jpeg',
fit: BoxFit.fill,
),
).toList(),
),
),
);
}
}
먼저 기본적인 PageView Widget을 살펴보자. Asset에 미리 넣어둔 파일명에서 숫자를 하나씩 mapping 하여 List를 구성해 준다. 이 이미지들은 SafeArea를 한 장씩 꽉 채우며 위치하게 된다. 좌우로 넘기면 작동이 잘 됨을 알 수 있다.
[1, 2, 3, 4, 5].map((number) => Image.asset('assets/img/image_$number.jpeg', fit: BoxFit.fill)).toList()
가독성은 떨어지지만 이해를 위해 길게 늘어뜨려 보자. 우리는 1, 2, 3, 4, 5로 이루어진 리스트의 요소(number type)들을 Image 객체로 매핑하는 과정을 거치고 나서 매핑된 객체를 다시 리스트로 변환한다. 이렇게 반환된 녀석이 children에 쏙 들어가게 되는 것이다.
2. PageView.builder
child: SafeArea(
child: Padding(
padding: EdgeInsets.only(bottom: 20),
child: PageView.builder(
controller: PageController(viewportFraction: 0.8), // 좌우 여백을 주기 위해 viewportFraction 설정
itemCount: 5,
itemBuilder: (context, index) {
return Padding(
padding: EdgeInsets.all(10),
child: ClipRRect(
borderRadius: BorderRadius.circular(20.0), // 테두리 둥글게 설정
child: Image.asset(
'assets/img/image_${index + 1}.jpeg',
fit: BoxFit.cover,
),
)
);
},
),
)
),
1번 예제의 경우 작동은 하지만 약간의 미학적 요소를 가미해 보자. 이를 위해 PageView의 builder를 통해 세부 설정을 해주어야 한다.
- 맨 위에 내비게이션바가 있기 때문에 사진이 잘리는 경우를 대비해 SafeArea로 감싸준다. 녹색 테두리에 해당한다.
- PageController의 viewportFraction을 0.8로 두어 화면 좌우 너비의 일부를 쓰게 한다. 만약 builder를 사용하지 않으면 default 값이 1이므로 1번 예제와 같은 화면이 나온다. 아래 그림의 파란색 테두리에 해당한다. 이어서 화면에 출력할 요소의 개수와 이 아이템들을 어떻게 구성할지 설정하고, 각 이미지별로 꼭짓점의 반지름을 잘라서 둥글게 만들어 준다. 내부에 상하좌우 패딩을 10씩 줌으로써 사진끼리 20의 간격이 생겼음을 알 수 있다. 이 간격과 20의 반지름의 길이가 동일하므로, 제대로 설계되었음을 눈으로 확인할 수 있다.
- 이어서 너무 꽉 찬 화면이 보기 싫어서 아래에 20의 패딩을 주었다. 빨간색 테두리에 해당한다.
전체 코드 보기
// import 'package:flutter/cupertino.dart';
//
// class HomeScreen extends StatelessWidget {
// const HomeScreen({Key? key}) : super(key: key);
//
// @override
// Widget build(BuildContext context) {
// return CupertinoPageScaffold(
// child: SafeArea(
// child: PageView(
// children: const [1, 2, 3, 4, 5].map(
// (number) => Image.asset(
// 'assets/img/image_$number.jpeg',
// fit: BoxFit.fill,
// ),
// ).toList(),
// ),
// ),
// );
// }
// }
import 'package:flutter/cupertino.dart';
class HomeScreen extends StatelessWidget {
const HomeScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: Text("iOS Swiping Images"),
),
child: SafeArea(
child: Padding(
padding: EdgeInsets.only(bottom: 20),
child: PageView.builder(
controller: PageController(viewportFraction: 0.8), // 좌우 여백을 주기 위해 viewportFraction 설정
itemCount: 5,
itemBuilder: (context, index) {
return Padding(
padding: EdgeInsets.all(10),
child: ClipRRect(
borderRadius: BorderRadius.circular(20.0), // 테두리 둥글게 설정
child: Image.asset(
'assets/img/image_${index + 1}.jpeg',
fit: BoxFit.cover,
),
)
);
},
),
)
),
);
}
}
'Dev > flutter' 카테고리의 다른 글
[Dev, flutter] 플러터로 iOS 앱 개발 시작하기 (8) - 앱 아이콘, 런치 스크린 (4) | 2024.09.03 |
---|---|
[Dev, flutter] 플러터로 iOS 앱 개발 시작하기 (7) - 화면 전환 (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 |