Flutter 앱: 달력 팝업 UI 개선

- 달력 열기 애니메이션 추가 (아래로 부드럽게 펼쳐짐)
- 툴바 영역 오버레이 제외 (툴바 아래부터 반투명 배경)
- 년월 텍스트 가운데 고정, 화살표는 옆에 별도 위치

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
caadiq 2026-01-13 18:31:54 +09:00
parent 21bd887f5e
commit 895d9c26a3

View file

@ -118,10 +118,14 @@ class _ScheduleViewState extends ConsumerState<ScheduleView> {
), ),
], ],
), ),
// // ( )
if (_showCalendar) ...[ if (_showCalendar) ...[
// // ( )
Positioned.fill( Positioned(
top: MediaQuery.of(context).padding.top + 56,
left: 0,
right: 0,
bottom: 0,
child: GestureDetector( child: GestureDetector(
onTap: () { onTap: () {
setState(() { setState(() {
@ -134,7 +138,7 @@ class _ScheduleViewState extends ConsumerState<ScheduleView> {
), ),
), ),
), ),
// // ()
Positioned( Positioned(
top: MediaQuery.of(context).padding.top + 56, top: MediaQuery.of(context).padding.top + 56,
left: 0, left: 0,
@ -196,32 +200,43 @@ class _ScheduleViewState extends ConsumerState<ScheduleView> {
), ),
// //
Expanded( Expanded(
child: GestureDetector( child: Stack(
onTap: _showCalendar alignment: Alignment.center,
? () { children: [
setState(() { // ( )
_showYearMonthPicker = !_showYearMonthPicker; GestureDetector(
_yearRangeStart = (_calendarViewDate.year ~/ 12) * 12; onTap: _showCalendar
}); ? () {
} setState(() {
: null, _showYearMonthPicker = !_showYearMonthPicker;
child: Center( _yearRangeStart = (_calendarViewDate.year ~/ 12) * 12;
child: Row( });
mainAxisSize: MainAxisSize.min, }
children: [ : null,
Text( child: Text(
'${displayDate.year}${displayDate.month}', '${displayDate.year}${displayDate.month}',
style: TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: _showYearMonthPicker color: _showYearMonthPicker
? AppColors.primary ? AppColors.primary
: AppColors.textPrimary, : AppColors.textPrimary,
),
), ),
if (_showCalendar) ...[ ),
const SizedBox(width: 4), ),
Icon( // ( )
if (_showCalendar)
Positioned(
// +
left: MediaQuery.of(context).size.width / 2 - 48 + 52,
child: GestureDetector(
onTap: () {
setState(() {
_showYearMonthPicker = !_showYearMonthPicker;
_yearRangeStart = (_calendarViewDate.year ~/ 12) * 12;
});
},
child: Icon(
_showYearMonthPicker _showYearMonthPicker
? Icons.keyboard_arrow_up ? Icons.keyboard_arrow_up
: Icons.keyboard_arrow_down, : Icons.keyboard_arrow_down,
@ -230,10 +245,9 @@ class _ScheduleViewState extends ConsumerState<ScheduleView> {
? AppColors.primary ? AppColors.primary
: AppColors.textPrimary, : AppColors.textPrimary,
), ),
], ),
], ),
), ],
),
), ),
), ),
// //
@ -271,16 +285,33 @@ class _ScheduleViewState extends ConsumerState<ScheduleView> {
/// ///
Widget _buildCalendarPopup(ScheduleState state, ScheduleController controller) { Widget _buildCalendarPopup(ScheduleState state, ScheduleController controller) {
return Material( return TweenAnimationBuilder<double>(
color: Colors.white, duration: const Duration(milliseconds: 200),
elevation: 8, curve: Curves.easeOut,
child: AnimatedCrossFade( tween: Tween(begin: 0.0, end: 1.0),
duration: const Duration(milliseconds: 150), builder: (context, value, child) {
crossFadeState: _showYearMonthPicker return ClipRect(
? CrossFadeState.showSecond child: Align(
: CrossFadeState.showFirst, alignment: Alignment.topCenter,
firstChild: _buildCalendarGrid(state, controller), heightFactor: value,
secondChild: _buildYearMonthPicker(), child: Opacity(
opacity: value,
child: child,
),
),
);
},
child: Material(
color: Colors.white,
elevation: 8,
child: AnimatedCrossFade(
duration: const Duration(milliseconds: 150),
crossFadeState: _showYearMonthPicker
? CrossFadeState.showSecond
: CrossFadeState.showFirst,
firstChild: _buildCalendarGrid(state, controller),
secondChild: _buildYearMonthPicker(),
),
), ),
); );
} }