이번에는 Item detail page 구현에 필요한 PageView 에 대해서 알아보겠습니다.
이미지가 여러개인 경우, 인디케이터도 같이 구현하는 방법에 대해서 알아보겠습니다.
개발환경 : 윈도우11, 안드로이드 스튜디오, flutter 3.0.1
구현한 화면은 아래와 같습니다.
인디케이터를 위해서 추가한 패키지는 아래와 같습니다.
smooth_page_indicator: ^1.0.0+2
./src/screens/home/item_detail_page.dart
class _ItemDetailPageState extends State<ItemDetailPage> {
final PageController _pageController = PageController();
Size? _size;
late String newItemKey;
@override
void initState() {
newItemKey = Get.arguments['itemKey'];
super.initState();
}
@override
void dispose() {
_pageController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
logger.d('item detail screen >> build >>> [$newItemKey]');
return FutureBuilder<ItemModel2>(
future: ItemService().getItem(newItemKey),
builder: (context, snapshot) {
if (snapshot.hasData) {
// FutureBuilder 의 snapshot 에서 게시글 데이터 가져오기
ItemModel2 itemModel = snapshot.data!;
// provider 입포트하고 고객 데이터 가져오기
// UserModel2 userModel = context.read<UserNotifier>().userModel!;
// UserModel1 userModel = UserController.to.userModel.value!;
return LayoutBuilder(
builder: (context, constraints) {
_size = MediaQuery.of(context).size;
// _statusBarHeight = MediaQuery.of(context).padding.top;
return Stack(
fit: StackFit.expand,
children: [
// 메인 정보를 표시하는 영역
Scaffold(
// 메인정보를 표시, CustomScrollView 는 listView 유사함
// listView 대신에 CustomScrollView 사용하는 이유는
// 화면을 구역으로 나눠서 각 구역마다 슬라이스를 구현할 수 있다,
body: CustomScrollView(
// controller: _scrollController,
// children 을 대신하는 slivers 있고, slivers 안에는 sliver 형식의 위젯을 넣어줘야 한다
slivers: [
// 업로드한 사진 정보를 표시하는 영역
_imageAppBar(itemModel),
// 일반위젯을 sliver 안에 넣으러면 SliverToBoxAdapter 로 wrapping 해야 함,
SliverToBoxAdapter(
child: Container(
// 스크롤 테스트를 위해서 높이를 길게 적용함,
height: _size!.height * 2,
color: Colors.cyan,
child: Center(child: Text(newItemKey)),
),
),
],
),
),
],
);
},
);
}
return Container(
color: Colors.white,
child: const Center(child: CircularProgressIndicator()),
);
},
);
}
// ******************** background 부분이 메인 수정 부분임 ********************
SliverAppBar _imageAppBar(ItemModel2 itemModel) {
return SliverAppBar(
// expandedHeight 에서는 세로 길이를 정해줄 수 있음,
expandedHeight: _size!.width,
// pinned: true 면 앱바 역역을 남기는 역할, false 면 스크롤시 같이 사라짐,
pinned: true,
flexibleSpace: FlexibleSpaceBar(
// background 로 이미지를 넣으면 됨, 이미지 표시
background: Stack(
children: [
// 좌/우로 스크롤 가능하게 처리,
PageView.builder(
controller: _pageController,
// 옆페이지로 이동시 포커스를 옆페이지로 이동시켜 로딩을 미리하게 설정함,
allowImplicitScrolling: true,
itemBuilder: (BuildContext context, int index) {
return ExtendedImage.network(
itemModel.imageDownloadUrls[index],
fit: BoxFit.cover,
// 캐싱을 했지만 다시 로딩하는 경우가 있어서 이미지 사이즈를 줄여줌,
scale: 0.1,
);
},
itemCount: itemModel.imageDownloadUrls.length,
),
Positioned(
bottom: padding_16,
// 중간으로 위치시키기 위해서 좌/우 0 으로 설정,
left: 0,
right: 0,
child: Center(
child: SmoothPageIndicator(
controller: _pageController, // PageController
count: itemModel.imageDownloadUrls.length,
effect: WormEffect(
activeDotColor: Theme.of(context).primaryColor,
dotColor: Theme.of(context).colorScheme.background,
radius: 4,
dotHeight: 8,
dotWidth: 8), // your preferred effect
onDotClicked: (index) {}),
),
),
],
),
),
);
}
}
'Flutter > 12 Clone 'Used Goods app'' 카테고리의 다른 글
[Flutter] Clone - 당근마켓41(Item detail & PageView) - 3 (2) | 2022.08.22 |
---|---|
[Flutter] Clone - 당근마켓40(Item detail & PageView) - 2 (0) | 2022.08.21 |
[Flutter] Clone - 당근마켓38(Item detail & CustomScrollView) (0) | 2022.08.21 |
[Flutter] Clone - 당근마켓37(Item read & Get.arguments) (2) | 2022.08.19 |
[Flutter] Clone - 당근마켓36(ItemModel upload - validators) (0) | 2022.08.19 |