-
Notifications
You must be signed in to change notification settings - Fork 1
20260319 #689 전체 애니메이션 개선 및 통일감 확보 #745
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
The head ref may contain hidden characters: "20260319_#689_\uC804\uCCB4_\uC560\uB2C8\uBA54\uC774\uC158_\uAC1C\uC120_\uBC0F_\uD1B5\uC77C\uAC10_\uD655\uBCF4"
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,13 +1,15 @@ | ||
| /// 화면 전환 방식을 정의. | ||
| /// [context.navigateTo]의 [type] 파라미터에서 사용. | ||
| /// | ||
| /// 스택 유지: [push], [pushReplacement], [fadePush] | ||
| /// 스택 유지: [push], [pushReplacement], [fadePush], [slideUp], [sharedAxisHorizontal] | ||
| /// 스택 클리어: [pushAndRemoveUntil], [fadeTransition], [clearStackImmediate] | ||
| enum NavigationTypes { | ||
| push, // 기존 화면 위에 추가 | ||
| pushReplacement, // 기존 화면을 대체 | ||
| pushAndRemoveUntil, // 기존 화면을 지우고 추가 | ||
| fadeTransition, // 스택을 지우고 Fade 애니메이션(800ms, easeInOut)으로 전환 | ||
| clearStackImmediate, // 스택을 지우고 애니메이션 없이 즉시 전환 | ||
| fadePush, // 스택 유지 + Fade 애니메이션 (Hero 전환과 함께 사용) | ||
| fadeTransition, // 스택을 지우고 Fade 애니메이션(400ms)으로 전환 | ||
| clearStackImmediate, // 스택을 지우고 Fade 애니메이션(400ms)으로 전환 (구 즉시 전환 대체) | ||
| fadePush, // 스택 유지 + Fade 애니메이션 | ||
| slideUp, // 스택 유지 + 아래에서 위로 슬라이드 (모달 느낌) | ||
| sharedAxisHorizontal, // 스택 유지 + 수평 SharedAxis (리스트→상세) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| import 'package:flutter/material.dart'; | ||
|
|
||
| /// 앱 전역 애니메이션 토큰 | ||
| /// | ||
| /// Duration과 Curve를 의미 있는 이름으로 중앙 관리. | ||
| /// 하드코딩된 Duration(milliseconds: N), Curves.easeInOut 사용 금지. | ||
| /// 반드시 이 클래스의 상수를 사용할 것. | ||
| class AppMotion { | ||
| AppMotion._(); | ||
|
|
||
| // ───────────────────────────────────────────── | ||
| // Duration 토큰 (5단계) | ||
| // ───────────────────────────────────────────── | ||
|
|
||
| /// 100ms — 터치 피드백, 즉각 반응 | ||
| static const Duration instant = Duration(milliseconds: 100); | ||
|
|
||
| /// 200ms — 기본 UI 전환, 스크롤 반응, 스켈레톤 fade | ||
| static const Duration fast = Duration(milliseconds: 200); | ||
|
|
||
| /// 300ms — 카드/리스트 등장, 상태 변경, 탭 전환 | ||
| static const Duration normal = Duration(milliseconds: 300); | ||
|
|
||
| /// 400ms — 페이지 전환, 모달 등장/퇴장 | ||
| static const Duration slow = Duration(milliseconds: 400); | ||
|
|
||
| /// 500ms — 온보딩, 특수 진입 (일반 UI에는 사용 금지) | ||
| static const Duration emphasis = Duration(milliseconds: 500); | ||
|
|
||
| // ───────────────────────────────────────────── | ||
| // Curve 토큰 (4종) | ||
| // ───────────────────────────────────────────── | ||
|
|
||
| /// 일반적인 상태 변화 — 토글, 색상 전환 | ||
| static const Curve standard = Curves.easeInOut; | ||
|
|
||
| /// 등장/진입 — 리스트 아이템, 카드 등장 (빠른 시작, 부드러운 끝) | ||
| static const Curve entry = Curves.easeOut; | ||
|
|
||
| /// 감속 — 컨텍스트 메뉴, 오버레이 (물리적 자연스러움) | ||
| static const Curve decelerate = Curves.easeOutCubic; | ||
|
|
||
| /// 버튼 눌림 spring back — AppPressable의 복귀 애니메이션 | ||
| static const Curve springOut = ElasticOutCurve(0.5); | ||
|
|
||
| // ───────────────────────────────────────────── | ||
| // 스켈레톤 shimmer 설정 | ||
| // ───────────────────────────────────────────── | ||
|
|
||
| /// 리스트 stagger 간격 — 아이템 인덱스 당 딜레이 (ms) | ||
| static const int staggerDelayMs = 30; | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,4 +1,5 @@ | ||||||||||||||||||||||||
| import 'package:flutter/material.dart'; | ||||||||||||||||||||||||
| import 'package:romrom_fe/models/app_motion.dart'; | ||||||||||||||||||||||||
| import 'package:romrom_fe/screens/chat_tab_screen.dart'; | ||||||||||||||||||||||||
| import 'package:romrom_fe/screens/home_tab_screen.dart'; | ||||||||||||||||||||||||
| import 'package:romrom_fe/screens/my_page_tab_screen.dart'; | ||||||||||||||||||||||||
|
|
@@ -55,7 +56,13 @@ class _MainScreenState extends State<MainScreen> { | |||||||||||||||||||||||
| return Scaffold( | ||||||||||||||||||||||||
| resizeToAvoidBottomInset: true, | ||||||||||||||||||||||||
| extendBody: false, | ||||||||||||||||||||||||
| body: _navigationTabScreens[_currentTabIndex], | ||||||||||||||||||||||||
| body: AnimatedSwitcher( | ||||||||||||||||||||||||
| duration: AppMotion.normal, | ||||||||||||||||||||||||
| switchInCurve: AppMotion.entry, | ||||||||||||||||||||||||
| switchOutCurve: AppMotion.entry, | ||||||||||||||||||||||||
| transitionBuilder: (child, animation) => FadeTransition(opacity: animation, child: child), | ||||||||||||||||||||||||
| child: KeyedSubtree(key: ValueKey<int>(_currentTabIndex), child: _navigationTabScreens[_currentTabIndex]), | ||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||
|
Comment on lines
+59
to
+65
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
기존의 🔧 IndexedStack + AnimatedOpacity 조합 제안- body: AnimatedSwitcher(
- duration: AppMotion.normal,
- switchInCurve: AppMotion.entry,
- switchOutCurve: AppMotion.entry,
- transitionBuilder: (child, animation) => FadeTransition(opacity: animation, child: child),
- child: KeyedSubtree(key: ValueKey<int>(_currentTabIndex), child: _navigationTabScreens[_currentTabIndex]),
- ),
+ body: IndexedStack(
+ index: _currentTabIndex,
+ children: _navigationTabScreens,
+ ),📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||
| bottomNavigationBar: CustomBottomNavigationBar( | ||||||||||||||||||||||||
| selectedIndex: _currentTabIndex, | ||||||||||||||||||||||||
| onTap: (index) { | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
context.navigateTo()대신MaterialPageRoute를 직접 사용하고 있습니다.코딩 가이드라인에 따르면 화면 전환 시
context.navigateTo()를 사용해야 합니다.🔧 context.navigateTo() 사용으로 변경
As per coding guidelines: "Use
context.navigateTo()for screen navigation (MaterialPageRoute direct usage prohibited)"📝 Committable suggestion
🤖 Prompt for AI Agents