GetX + SliverAppBar

Ohgyuchan·2023년 4월 26일
0

Flutter

목록 보기
21/25
post-thumbnail

SliverAppBar 적용 화면

SliverAppBar 적용 예시 코드

import 'package:get/get.dart';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_markdown/flutter_markdown.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';

import '../../../themes/themes.dart';
import '../../../widgets/widgets.dart';
import '../../constants/constants.dart';

class EventPage extends StatelessWidget {
  EventPage({Key? key}) : super(key: key);

  final animationController = Get.put(MyAnimationController());

  
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        bottom: false,
        child: CustomScrollView(
          shrinkWrap: true,
          controller: animationController.appBarScrollController,
          slivers: [
            AnimatedBuilder(
                animation: animationController.appBarColorTween,
                builder: (context, child) {
                  return SliverAppBar(
                    foregroundColor: animationController.appBarColorTween.value,
                    title: Text(
                      'ZOOM 초대 + 환경 영화 상영 + 기후 토크',
                      style: AppTextStyle.instance.subtitle1.copyWith(
                        color: animationController.appBarColorTween.value,
                      ),
                    ),
                    pinned: true,
                    expandedHeight: 300.h,
                    flexibleSpace: FlexibleSpaceBar(
                      background: Column(
                        children: [
                          ImageProviderUtils.instance
                              .networkImageUtilWithFitHeight(
                            'https://eventusstorage.blob.core.windows.net/evs/Image/occ/50286/ProjectInfo/Cover/7f389dd99ebe429192a3ea46ab3f91ec.jpg',
                          ),
                          SizedBox(
                            width: Get.width,
                            child: Image.network(
                              "https://eventusstorage.blob.core.windows.net/evs/Image/occ/51482/ProjectInfo/Cover/06804b70493d40f0956000c50b683df0.jpg",
                            ),
                          ),
                        ],
                      ),
                    ),
                  );
                }),
            SliverList(
              delegate: SliverChildListDelegate.fixed([
                ListView(
                  shrinkWrap: true,
                  physics: const NeverScrollableScrollPhysics(),
                  children: [
                    Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Text(
                            '[ZOOM 초대, 환경 영화 영상제 + 기후 토크] 우리의 식생활, 멸종을 부르다',
                            style: AppTextStyle.instance.title2,
                          ),
                          Text(
                            '#기후위기 #유기농 #채식 #비건 #멸종',
                            style: TextStyle(
                              color: Colors.purple[200],
                              fontWeight: FontWeight.bold,
                            ),
                          ),
                          Row(
                            children: const [
                              ProfileImage(
                                imgUrl:
                                    "https://eventusstorage.blob.core.windows.net/evs/UploadedFiles/occ/TopLogoImage/117ae7e7e6694fae91aef5984e8ac7e7.png",
                                imgSize: 50,
                              ),
                              Text(
                                '(사)유기농문화센터',
                                style: TextStyle(
                                  fontWeight: FontWeight.bold,
                                ),
                              ),
                              Icon(CupertinoIcons.forward),
                            ],
                          ),
                          const Divider(),
                          Text(
                            '행사 소개',
                            style: AppTextStyle.instance.title3,
                          ),
                          const Divider(),
                          Text(
                            '일시\t04월 28일(금) 10:30 ~ 13:00',
                            style: AppTextStyle.instance.body3,
                          ),
                          const SizedBox(
                            height: 10,
                          ),
                          Row(
                            children: [
                              const Icon(Icons.calendar_today),
                              Text(
                                '구글캘린더에 추가하기',
                                style: AppTextStyle.instance.body3,
                              ),
                            ],
                          ),
                          const SizedBox(
                            height: 10,
                          ),
                          Row(
                            mainAxisAlignment: MainAxisAlignment.spaceBetween,
                            children: [
                              Text(
                                '신청\t03월 29일(수) 00:00 ~ 04월 27일(목) 23:30',
                                style: AppTextStyle.instance.body3,
                              ),
                              const CategoryChip(
                                label: '모집중',
                              )
                            ],
                          ),
                          const SizedBox(
                            height: 10,
                          ),
                          Text(
                            '비용\t무료',
                            style: AppTextStyle.instance.body3,
                          ),
                          const SizedBox(
                            height: 10,
                          ),
                          Text(
                            '장소\t온라인',
                            style: AppTextStyle.instance.body3,
                          ),
                          const SizedBox(
                            height: 10,
                          ),
                          Text(
                            '스트리밍\tZoom',
                            style: AppTextStyle.instance.body3,
                          ),
                          const Divider(),
                          Text(
                            '취소 및 환불 규정',
                            style: AppTextStyle.instance.title3,
                          ),
                          const Divider(),
                          const Markdown(
                              physics: NeverScrollableScrollPhysics(),
                              softLineBreak: true,
                              shrinkWrap: true,
                              styleSheetTheme:
                                  MarkdownStyleSheetBaseTheme.cupertino,
                              data:
                                  '> - 행사의 취소/환불 기간은 행사 호스트가 설정한 신청기간과 동일합니다.\n> - 신청한 행사의 신청 정보 수정 및 취소/환불은 ‘마이페이지-신청한 행사’에서 할 수 있습니다.\n> - 결제 수단, 환불 신청 시점, 환불 사유에 따라 환불 수수료가 부과될 수 있습니다.\n> - 위에 대한 자세한 내용은 ‘취소 및 환불규정’에서 확인할 수 있습니다.\n> - 신청기간 마감 이후의 신청 정보 수정 및 취소/환불은 행사 호스트에게 문의 부탁드립니다.\n> - 행사에 관련된 사항은 하단의‘문의하기’를 통해 행사 호스트에게 문의 부탁 드립니다.\n> * 이벤터스는 통신판매 중개자이며, 해당 행사의 호스트가 아닙니다.'),
                        ],
                      ),
                    ),
                    SizedBox(
                      height: 60.h,
                    ),
                  ],
                ),
              ]),
            ),
          ],
        ),
      ),
      bottomSheet: Container(
        decoration: BoxDecoration(
          color: Get.theme.colorScheme.background,
          border: Border(
            top: BorderSide(
              color: Get.theme.colorScheme.onBackground,
              width: 1,
            ),
          ),
        ),
        child: ApplyButton(
          label: '신청하기',
          applyOnTap: () {},
          sharingOnTap: () {},
          likeOnTap: () {},
        ),
      ),
    );
  }
}

class MyAnimationController extends GetxController
    with GetTickerProviderStateMixin {
  ScrollController appBarScrollController = ScrollController();
  AnimationController? animationController;
  AnimationController? appBarAnimationController;
  double scrollPositionToAlpha = 0;
  late Animation<Color?> color;
  late Animation<Color?> appBarColorTween;

  
  void onInit() {
    super.onInit();
    animationController = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 500),
    );
    appBarAnimationController = AnimationController(vsync: this);
    color = ColorTween(
            begin: Get.theme.colorScheme.primary,
            end: Get.theme.colorScheme.background)
        .animate(animationController!);

    appBarColorTween = ColorTween(
      begin: Colors.transparent,
      end: Colors.black,
    ).animate(appBarAnimationController!);
    appBarScrollController.addListener(() {
      if (appBarScrollController.offset > 255) {
        scrollPositionToAlpha = 255;
      } else {
        scrollPositionToAlpha = appBarScrollController.offset;
      }
      appBarAnimationController!.value = scrollPositionToAlpha / 255;
    });
  }
}
profile
Flutter 개발자

0개의 댓글