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());
@override
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;
@override
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;
});
}
}