2023. 5. 27. 21:58ㆍ모바일어플개발/Flutter
안녕하세요~ totally 개발자입니다.
photo_view
어플을 개발하다보면 사진을 올리고 그 사진을 볼 수 있도록 탭해서 사진을 확대, 축소할 수 있는 기능이 필요한 경우가 있습니다. 그런 경우에 사용할 수 있는 패키지로 photo_view를 사용할 수 있습니다. 패키지 버전이 초기 버전이기는 하지만 간단하게 사용할 수 있기 때문에 활용해보면 좋습니다. 먼저 3장의 이미지를 준비해주셔야 합니다 (pixabay를 활용했습니다)
Step 1: pubspec.yaml에 photo_view를 설치해주시고 flutter pub get 해줍니다.

Step 2: 먼저 사진을 탭했을 때 보여주는 photoView.dart 파일을 하나 생성해주시고 코드를 작성해줍니다. 전체 코드는 맨 아래에 있으니 참고하시기 바랍니다. 여기에서 5~8번째 줄에 변수들을 선언하시고 추후 arguments로 패스할 수 있도록 합니다. 15번째 줄에 보시면 PageController 인스턴스 변수도 만들어주시고 18번째 줄에 인스턴스화 해줍니다. 여기에서 initialPage 매개변수를 currentIndex를 주셔서 어떤 사진을 클릭했는지를 알 수 있도록 전달해 주시면 됩니다.

Step 3: 그 다음 여러 장의 사진을 좌우로 스크롤하며 볼 수 있도록 만들어주는 PageView.builder를 먼저 작성하시고 그 다음 제가 아래 빨간색, 연두색, 노랑색으로 표시한 부분들을 작성합니다. 빨간 색의 PhotoView 위젯은 사진을 표시하는 위젯, 연두색 부분은 사진을 보고 닫을 수 있는 버튼, 노랑색 부분은 현재 슬라이드 위치를 표시하는 Indicator 역할을 합니다.

Step 4: main.dart 부분에 다음처럼 작성합니다.여기에서 28~32번째 줄에서는 image 링크 리스트를 만들어주시고 39번째 줄에 ListView.builder를 통해 이미지들을 쭉 세로로 보여줍니다. 그리고 그 화면을 탭했을 때 위에서 만든 PhotoViewPage로 넘어갈 수 있도록 GestureDetector를 통해 구현해줍니다. 만약 Gesture 부분을 자동으로 하고 싶은 경우에는 PhotoViewGallery 위젯을 사용하셔서 구현할 수도 있습니다. (PhotoViewGallery.builder 형태)

Step 5: 테스트해본 모습입니다.

[전체 소스 코드]
[photoView.dart]
import 'package:flutter/material.dart'; | |
import 'package:photo_view/photo_view.dart'; | |
class PhotoViewPage extends StatefulWidget { | |
List<String> imagePaths; | |
int currentIndex; | |
PhotoViewPage( | |
{super.key, required this.imagePaths, required this.currentIndex}); | |
@override | |
State<PhotoViewPage> createState() => _PhotoViewPageState(); | |
} | |
class _PhotoViewPageState extends State<PhotoViewPage> { | |
late PageController _controller; | |
@override | |
Widget build(BuildContext context) { | |
_controller = PageController(initialPage: widget.currentIndex); | |
return Scaffold( | |
body: PageView.builder( | |
controller: _controller, | |
itemCount: 3, | |
itemBuilder: (context, index) { | |
return Stack( | |
children: [ | |
PhotoView( | |
imageProvider: NetworkImage(widget.imagePaths[index]), | |
), | |
Align( | |
alignment: Alignment.topRight, | |
child: Container( | |
margin: const EdgeInsets.only(top: 45, right: 20), | |
decoration: const BoxDecoration( | |
shape: BoxShape.circle, | |
color: Colors.white24, | |
), | |
child: IconButton( | |
icon: const Icon( | |
Icons.close, | |
color: Colors.white, | |
), | |
onPressed: () => Navigator.of(context).pop(), | |
), | |
), | |
), | |
Align( | |
alignment: Alignment.bottomCenter, | |
child: Container( | |
margin: const EdgeInsets.only(bottom: 30), | |
child: Text( | |
"${index + 1} / ${widget.imagePaths.length}", | |
style: const TextStyle(color: Colors.white), | |
), | |
), | |
) | |
], | |
); | |
}), | |
); | |
} | |
} |
[main.dart]
import 'package:flutter/material.dart'; | |
import 'package:project/photoView.dart'; | |
void main() { | |
runApp(const MyApp()); | |
} | |
class MyApp extends StatelessWidget { | |
const MyApp({Key? key}) : super(key: key); | |
@override | |
Widget build(BuildContext context) { | |
return const MaterialApp( | |
title: 'Flutter App', | |
home: MainPage(), | |
); | |
} | |
} | |
class MainPage extends StatefulWidget { | |
const MainPage({Key? key}) : super(key: key); | |
@override | |
State<MainPage> createState() => _MainPageState(); | |
} | |
class _MainPageState extends State<MainPage> { | |
List<String> imagePaths = [ | |
'https://cdn.pixabay.com/photo/2023/04/30/09/43/flower-7960192_1280.jpg', | |
'https://cdn.pixabay.com/photo/2023/04/30/22/01/ocean-7961695_1280.jpg', | |
'https://cdn.pixabay.com/photo/2023/05/21/07/59/iceberg-8008071_1280.jpg' | |
]; | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar( | |
title: const Text('My App'), | |
), | |
body: ListView.builder( | |
itemCount: imagePaths.length, | |
itemBuilder: (context, index) { | |
return GestureDetector( | |
onTap: () { | |
Navigator.of(context) | |
.push(MaterialPageRoute(builder: (context) { | |
return PhotoViewPage( | |
imagePaths: imagePaths, currentIndex: index); | |
})); | |
}, | |
child: Image( | |
image: NetworkImage(imagePaths[index]), | |
), | |
); | |
}, | |
)); | |
} | |
} |
References:
https://pub.dev/packages/photo_view
photo_view | Flutter Package
Photo View provides a gesture sensitive zoomable widget. Photo View is largely used to show interactive images and other stuff such as SVG.
pub.dev
[유튜브 강좌 영상]