11import 'package:flutter/material.dart' ;
22import 'package:ongi/core/app_light_background.dart' ;
33import 'package:ongi/core/app_colors.dart' ;
4+ import 'dart:ui' ; // Added for ImageFilter
45
56class PhotoDateScreen extends StatefulWidget {
67 const PhotoDateScreen ({super .key});
@@ -10,12 +11,292 @@ class PhotoDateScreen extends StatefulWidget {
1011}
1112
1213class _PhotoDateScreenState extends State <PhotoDateScreen > {
14+ int _currentPage = 1 ;
15+ final List <Map <String , String >> _photos = [
16+ {
17+ 'main' : 'assets/images/sample_family_photo.png' ,
18+ 'sub' : 'assets/images/sample_family_photo.png' ,
19+ 'profile' : 'assets/images/users/elderly_woman.png' ,
20+ 'text' : '엄마는 금정산 등산 덕에 활기가 너무 좋다~' ,
21+ 'location' : '부산광역시, 장전동' ,
22+ },
23+ {
24+ 'main' : 'assets/images/sample_family_photo.png' ,
25+ 'sub' : 'assets/images/sample_family_photo.png' ,
26+ 'profile' : 'assets/images/users/elderly_woman.png' ,
27+ 'text' : '오늘은 가족과 함께 산책 헤헤' ,
28+ 'location' : '서울특별시, 강남구' ,
29+ },
30+ {
31+ 'main' : 'assets/images/sample_family_photo.png' ,
32+ 'sub' : 'assets/images/sample_family_photo.png' ,
33+ 'profile' : 'assets/images/users/elderly_woman.png' ,
34+ 'text' : '즐거운 여행의 추억 :)' ,
35+ 'location' : '경기도, 수원시' ,
36+ },
37+ ];
38+
1339 @override
1440 Widget build (BuildContext context) {
41+ final screenWidth = MediaQuery .of (context).size.width;
42+ final screenHeight = MediaQuery .of (context).size.height;
43+ final cardWidth = screenWidth;
44+ final cardHeight = screenHeight * 0.4 ;
45+ // 카드 크기 되돌림
1546 return Scaffold (
1647 backgroundColor: Colors .transparent,
1748 body: AppLightBackground (
18- child: Padding (padding: const EdgeInsets .all (24 )),
49+ child: Column (
50+ crossAxisAlignment: CrossAxisAlignment .start,
51+ children: [
52+ const SizedBox (height: 125 ),
53+ Expanded (
54+ child: Padding (
55+ padding: const EdgeInsets .symmetric (horizontal: 40 ),
56+ child: Column (
57+ crossAxisAlignment: CrossAxisAlignment .start,
58+ children: [
59+ // 타이틀
60+ const Text (
61+ '우리가족의' ,
62+ style: TextStyle (
63+ fontSize: 60 ,
64+ fontWeight: FontWeight .w200,
65+ height: 1.2 ,
66+ color: AppColors .ongiOrange,
67+ ),
68+ ),
69+ const Text (
70+ '마음 기록' ,
71+ style: TextStyle (
72+ fontSize: 60 ,
73+ fontWeight: FontWeight .w800,
74+ height: 1.2 ,
75+ color: AppColors .ongiOrange,
76+ ),
77+ ),
78+ const SizedBox (height: 32 ),
79+ // 사진 카드 PageView
80+ Center (
81+ child: SizedBox (
82+ width: cardWidth,
83+ height: cardHeight,
84+ child: PageView .builder (
85+ itemCount: _photos.length,
86+ controller: PageController (viewportFraction: 0.78 , initialPage: _currentPage),
87+ onPageChanged: (idx) => setState (() => _currentPage = idx),
88+ itemBuilder: (context, idx) {
89+ final photo = _photos[idx];
90+ final isActive = idx == _currentPage;
91+ return AnimatedContainer (
92+ duration: const Duration (milliseconds: 200 ),
93+ margin: EdgeInsets .symmetric (
94+ horizontal: isActive ? 0 : 8 ,
95+ vertical: isActive ? 0 : 16 ,
96+ ),
97+ width: cardWidth,
98+ height: cardHeight,
99+ child: Stack (
100+ clipBehavior: Clip .none,
101+ children: [
102+ ClipRRect (
103+ borderRadius: BorderRadius .circular (32 ),
104+ child: isActive
105+ ? Image .asset (
106+ photo['main' ]! ,
107+ width: cardWidth,
108+ height: cardHeight,
109+ fit: BoxFit .cover,
110+ )
111+ : ImageFiltered (
112+ imageFilter: ImageFilter .blur (sigmaX: 8 , sigmaY: 8 ),
113+ child: Opacity (
114+ opacity: 0.7 ,
115+ child: Image .asset (
116+ photo['main' ]! ,
117+ width: cardWidth,
118+ height: cardHeight,
119+ fit: BoxFit .cover,
120+ ),
121+ ),
122+ ),
123+ ),
124+ // 좌상단 서브(프로필) 사진
125+ Positioned (
126+ left: 16 ,
127+ top: 16 ,
128+ child: Container (
129+ width: 88 ,
130+ height: 100 ,
131+ decoration: BoxDecoration (
132+ border: Border .all (color: AppColors .ongiOrange, width: 3 ),
133+ borderRadius: BorderRadius .circular (15 ),
134+ ),
135+ child: ClipRRect (
136+ borderRadius: BorderRadius .circular (15 ),
137+ child: Image .asset (
138+ photo['sub' ] ?? photo['main' ]! ,
139+ fit: BoxFit .cover,
140+ ),
141+ ),
142+ ),
143+ ),
144+ // 하단 오버레이
145+ Positioned (
146+ left: 0 ,
147+ right: 0 ,
148+ bottom: 0 ,
149+ child: Container (
150+ padding: const EdgeInsets .fromLTRB (20 , 16 , 20 , 24 ),
151+ decoration: BoxDecoration (
152+ borderRadius: const BorderRadius .only (
153+ bottomLeft: Radius .circular (32 ),
154+ bottomRight: Radius .circular (32 ),
155+ ),
156+ gradient: LinearGradient (
157+ begin: Alignment .topCenter,
158+ end: Alignment .bottomCenter,
159+ colors: [
160+ Colors .black.withOpacity (0.0 ),
161+ Colors .black.withOpacity (0.4 ),
162+ ],
163+ ),
164+ ),
165+ child: Column (
166+ crossAxisAlignment: CrossAxisAlignment .start,
167+ mainAxisSize: MainAxisSize .min,
168+ children: [
169+ Row (
170+ children: [
171+ // 원형 프로필
172+ CircleAvatar (
173+ radius: 16 ,
174+ backgroundImage: AssetImage (photo['profile' ]! ),
175+ ),
176+ const SizedBox (width: 8 ),
177+ Expanded (
178+ child: Text (
179+ photo['text' ]! ,
180+ style: const TextStyle (
181+ color: Colors .white,
182+ fontSize: 10 ,
183+ fontFamily: 'Pretendard' ,
184+ fontWeight: FontWeight .w500,
185+ shadows: [
186+ Shadow (
187+ color: Colors .black38,
188+ blurRadius: 4 ,
189+ offset: Offset (0 , 2 ),
190+ ),
191+ ],
192+ ),
193+ ),
194+ ),
195+ ],
196+ ),
197+ const SizedBox (height: 8 ),
198+ // 위치 버튼 스타일
199+ Align (
200+ alignment: Alignment .center,
201+ child: Container (
202+ padding: const EdgeInsets .symmetric (horizontal: 8 , vertical: 2 ),
203+ decoration: BoxDecoration (
204+ color: Colors .white,
205+ borderRadius: BorderRadius .circular (20 ),
206+ ),
207+ child: Row (
208+ mainAxisSize: MainAxisSize .min,
209+ children: [
210+ Icon (Icons .place, color: AppColors .ongiOrange, size: 16 ),
211+ const SizedBox (width: 4 ),
212+ Text (
213+ photo['location' ]! ,
214+ style: TextStyle (
215+ color: AppColors .ongiOrange,
216+ fontSize: 11 ,
217+ fontWeight: FontWeight .w500,
218+ fontFamily: 'Pretendard' ,
219+ ),
220+ ),
221+ ],
222+ ),
223+ ),
224+ ),
225+ ],
226+ ),
227+ ),
228+ ),
229+ ],
230+ ),
231+ );
232+ },
233+ ),
234+ ),
235+ ),
236+ // 감정 태그 버튼
237+ Row (
238+ mainAxisAlignment: MainAxisAlignment .center,
239+ children: [
240+ _buildTagButton ('뿌듯함' , AppColors .ongiOrange),
241+ const SizedBox (width: 6 ),
242+ _buildTagButton ('기운이 남' , AppColors .ongiOrange),
243+ const SizedBox (width: 6 ),
244+ _buildTagButton ('들뜸' , AppColors .ongiOrange),
245+ ],
246+ ),
247+ const SizedBox (height: 16 ),
248+ // 페이지인디케이터
249+ Row (
250+ mainAxisAlignment: MainAxisAlignment .center,
251+ children: [
252+ for (int i = 0 ; i < _photos.length; i++ ) ...[
253+ _buildIndicator (i == _currentPage),
254+ if (i != _photos.length - 1 ) const SizedBox (width: 6 ),
255+ ]
256+ ],
257+ ),
258+ ],
259+ ),
260+ ),
261+ ),
262+ ],
263+ ),
264+ ),
265+ );
266+ }
267+
268+ Widget _buildTagButton (String text, Color color) {
269+ return OutlinedButton (
270+ onPressed: () {},
271+ style: OutlinedButton .styleFrom (
272+ side: BorderSide (color: color, width: 1.5 ),
273+ shape: RoundedRectangleBorder (
274+ borderRadius: BorderRadius .circular (20 ),
275+ ),
276+ backgroundColor: AppColors .ongiOrange,
277+ padding: const EdgeInsets .symmetric (horizontal: 10 , vertical: 15 ),
278+ minimumSize: Size .zero,
279+ visualDensity: VisualDensity .compact,
280+ ),
281+ child: Text (
282+ text,
283+ style: TextStyle (
284+ color: Colors .white,
285+ fontWeight: FontWeight .w700,
286+ fontSize: 12 ,
287+ fontFamily: 'Pretendard' ,
288+ ),
289+ ),
290+ );
291+ }
292+
293+ Widget _buildIndicator (bool isActive) {
294+ return Container (
295+ width: isActive ? 15 : 10 ,
296+ height: isActive ? 15 : 10 ,
297+ decoration: BoxDecoration (
298+ color: isActive ? AppColors .ongiOrange : Colors .grey[300 ],
299+ borderRadius: BorderRadius .circular (8 ),
19300 ),
20301 );
21302 }
0 commit comments