본문 바로가기

Flutter/12 Clone 'Used Goods app'

[Flutter] Clone - 당근마켓38(Item detail & CustomScrollView)

이번에는 CustomScrollView 에 대해서 알아보겠습니다.

CustomScrollView 내부에는 slivers[] 를 이용하여 화면을 구역으로 나눠서 각 구역마다 슬라이스를 구현할 수 있다.

일반적으로 slivers 내부에는 Sliver 스타일의 위젯을 넣을수 있다. SliverAppBar 는 기존 AppBar 와 유사한 기능을 하고, 일반 위젯을 사용하려면 SliverToBoxAdapter 으로 wrapping 하여 사용하면 된다. 그 외에도 많은 기능이 있으니 참고하세요.

개발환경 : 윈도우11, 안드로이드 스튜디오, flutter 3.0.1

 

 

구현한 화면은 아래와 같습니다.

 

 

 

 

./src/screens/home/item_detail_page.dart

- appBar 사용안하고, body 에서 CustomScrollView&SilverAppBar 조합으로 appBar 처럼 동작하게 구현.

 

import 'package:flutter/material.dart';
import 'package:get/get.dart';

import '../../models/item_model.dart';
import '../../repo/item_service.dart';
import '../../utils/logger.dart';

class ItemDetailPage extends StatefulWidget {
  const ItemDetailPage({Key? key}) : super(key: key);

  @override
  _ItemDetailPageState createState() => _ItemDetailPageState();
}

class _ItemDetailPageState extends State<ItemDetailPage> {

  Size? _size;
  late String newItemKey;

  @override
  void initState() {
    newItemKey = Get.arguments['itemKey'];
    super.initState();
  }

  @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!;

          return LayoutBuilder(
            builder: (context, constraints) {
              _size = MediaQuery.of(context).size;
              return Stack(
              // fit 은 Stack 에 있는 모든 아이콘들이 화면에 가득차게 하는 옵션,
              // 현재는 Scaffold 만 있어서 다른 효과 없음,
                fit: StackFit.expand,
                children: [
                  // 메인 정보를 표시하는 영역
                  Scaffold(
                    // 메인정보를 표시, CustomScrollView 는 listView 유사함
                    // listView 대신에 CustomScrollView 사용하는 이유는
                    // slivers 를 이용해서 화면을 구역으로 나눠서 각 구역마다 슬라이스를 구현할 수 있다,
                    body: CustomScrollView(
                      // children 을 대신하는 slivers 있고, slivers 안에는 sliver 형식의 위젯 추가 가능
                      slivers: [
                        _imageAppBar(itemModel),
                        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()),
        );
      },
    );
  }

  SliverAppBar _imageAppBar(ItemModel2 itemModel) {
    return SliverAppBar(
      // expandedHeight 에서는 세로 길이를 정해줄 수 있음,
      expandedHeight: _size!.width,
      // pinned: true 면 앱바 역역을 남기는 역할, false 면 스크롤시 같이 사라짐,
      pinned: true,
      flexibleSpace: const FlexibleSpaceBar(
        centerTitle: true,
        title: Text('testing', style: TextStyle(color: Colors.black),),
        background: FlutterLogo(),
      ),
    );
  }
}