feat: adopt material 3 theme and billing adjustments
This commit is contained in:
@@ -5,7 +5,7 @@ import '../widgets/add_subscription/add_subscription_header.dart';
|
||||
import '../widgets/add_subscription/add_subscription_form.dart';
|
||||
import '../widgets/add_subscription/add_subscription_event_section.dart';
|
||||
import '../widgets/add_subscription/add_subscription_save_button.dart';
|
||||
import '../theme/app_colors.dart';
|
||||
// import '../theme/app_colors.dart';
|
||||
|
||||
/// 새로운 구독을 추가하는 화면
|
||||
class AddSubscriptionScreen extends StatefulWidget {
|
||||
@@ -45,7 +45,7 @@ class _AddSubscriptionScreenState extends State<AddSubscriptionScreen>
|
||||
_controller.scrollController.addListener(_onScroll);
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: AppColors.backgroundColor,
|
||||
backgroundColor: Theme.of(context).colorScheme.surface,
|
||||
extendBodyBehindAppBar: true,
|
||||
appBar: AddSubscriptionAppBar(
|
||||
controller: _controller,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../providers/app_lock_provider.dart';
|
||||
import '../theme/app_colors.dart';
|
||||
// import '../theme/app_colors.dart';
|
||||
|
||||
class AppLockScreen extends StatelessWidget {
|
||||
const AppLockScreen({super.key});
|
||||
@@ -13,26 +13,26 @@ class AppLockScreen extends StatelessWidget {
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(
|
||||
Icon(
|
||||
Icons.lock_outline,
|
||||
size: 80,
|
||||
color: AppColors.navyGray,
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
const Text(
|
||||
Text(
|
||||
'앱이 잠겨 있습니다',
|
||||
style: TextStyle(
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: AppColors.darkNavy,
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
const Text(
|
||||
Text(
|
||||
'생체 인증으로 잠금을 해제하세요',
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
color: AppColors.navyGray,
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 32),
|
||||
@@ -41,15 +41,16 @@ class AppLockScreen extends StatelessWidget {
|
||||
final appLock = context.read<AppLockProvider>();
|
||||
final success = await appLock.authenticate();
|
||||
if (!success && context.mounted) {
|
||||
final cs = Theme.of(context).colorScheme;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
'인증에 실패했습니다. 다시 시도해주세요.',
|
||||
style: TextStyle(
|
||||
color: AppColors.pureWhite,
|
||||
color: cs.onPrimary,
|
||||
),
|
||||
),
|
||||
backgroundColor: AppColors.dangerColor,
|
||||
backgroundColor: cs.error,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../providers/category_provider.dart';
|
||||
import '../theme/app_colors.dart';
|
||||
// import '../theme/app_colors.dart';
|
||||
import '../l10n/app_localizations.dart';
|
||||
|
||||
class CategoryManagementScreen extends StatefulWidget {
|
||||
@@ -43,13 +43,13 @@ class _CategoryManagementScreenState extends State<CategoryManagementScreen> {
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text(
|
||||
title: Text(
|
||||
'카테고리 관리',
|
||||
style: TextStyle(
|
||||
color: AppColors.pureWhite,
|
||||
),
|
||||
style: Theme.of(context).textTheme.titleLarge?.copyWith(
|
||||
color: Theme.of(context).colorScheme.onPrimary,
|
||||
),
|
||||
),
|
||||
backgroundColor: AppColors.primaryColor,
|
||||
backgroundColor: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
body: Consumer<CategoryProvider>(
|
||||
builder: (context, provider, child) {
|
||||
@@ -66,10 +66,12 @@ class _CategoryManagementScreenState extends State<CategoryManagementScreen> {
|
||||
children: [
|
||||
TextFormField(
|
||||
controller: _nameController,
|
||||
decoration: const InputDecoration(
|
||||
decoration: InputDecoration(
|
||||
labelText: '카테고리 이름',
|
||||
labelStyle: TextStyle(
|
||||
color: AppColors.navyGray,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
validator: (value) {
|
||||
@@ -81,11 +83,13 @@ class _CategoryManagementScreenState extends State<CategoryManagementScreen> {
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
DropdownButtonFormField<String>(
|
||||
value: _selectedColor,
|
||||
decoration: const InputDecoration(
|
||||
initialValue: _selectedColor,
|
||||
decoration: InputDecoration(
|
||||
labelText: '색상 선택',
|
||||
labelStyle: TextStyle(
|
||||
color: AppColors.navyGray,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
items: [
|
||||
@@ -93,32 +97,42 @@ class _CategoryManagementScreenState extends State<CategoryManagementScreen> {
|
||||
value: '#1976D2',
|
||||
child: Text(
|
||||
AppLocalizations.of(context).colorBlue,
|
||||
style: const TextStyle(
|
||||
color: AppColors.darkNavy))),
|
||||
style: TextStyle(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurface))),
|
||||
DropdownMenuItem(
|
||||
value: '#4CAF50',
|
||||
child: Text(
|
||||
AppLocalizations.of(context).colorGreen,
|
||||
style: const TextStyle(
|
||||
color: AppColors.darkNavy))),
|
||||
style: TextStyle(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurface))),
|
||||
DropdownMenuItem(
|
||||
value: '#FF9800',
|
||||
child: Text(
|
||||
AppLocalizations.of(context).colorOrange,
|
||||
style: const TextStyle(
|
||||
color: AppColors.darkNavy))),
|
||||
style: TextStyle(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurface))),
|
||||
DropdownMenuItem(
|
||||
value: '#F44336',
|
||||
child: Text(
|
||||
AppLocalizations.of(context).colorRed,
|
||||
style: const TextStyle(
|
||||
color: AppColors.darkNavy))),
|
||||
style: TextStyle(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurface))),
|
||||
DropdownMenuItem(
|
||||
value: '#9C27B0',
|
||||
child: Text(
|
||||
AppLocalizations.of(context).colorPurple,
|
||||
style: const TextStyle(
|
||||
color: AppColors.darkNavy))),
|
||||
style: TextStyle(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurface))),
|
||||
],
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
@@ -128,39 +142,51 @@ class _CategoryManagementScreenState extends State<CategoryManagementScreen> {
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
DropdownButtonFormField<String>(
|
||||
value: _selectedIcon,
|
||||
decoration: const InputDecoration(
|
||||
initialValue: _selectedIcon,
|
||||
decoration: InputDecoration(
|
||||
labelText: '아이콘 선택',
|
||||
labelStyle: TextStyle(
|
||||
color: AppColors.navyGray,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
items: const [
|
||||
items: [
|
||||
DropdownMenuItem(
|
||||
value: 'subscriptions',
|
||||
child: Text('구독',
|
||||
style:
|
||||
TextStyle(color: AppColors.darkNavy))),
|
||||
style: TextStyle(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurface))),
|
||||
DropdownMenuItem(
|
||||
value: 'movie',
|
||||
child: Text('영화',
|
||||
style:
|
||||
TextStyle(color: AppColors.darkNavy))),
|
||||
style: TextStyle(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurface))),
|
||||
DropdownMenuItem(
|
||||
value: 'music_note',
|
||||
child: Text('음악',
|
||||
style:
|
||||
TextStyle(color: AppColors.darkNavy))),
|
||||
style: TextStyle(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurface))),
|
||||
DropdownMenuItem(
|
||||
value: 'fitness_center',
|
||||
child: Text('운동',
|
||||
style:
|
||||
TextStyle(color: AppColors.darkNavy))),
|
||||
style: TextStyle(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurface))),
|
||||
DropdownMenuItem(
|
||||
value: 'shopping_cart',
|
||||
child: Text('쇼핑',
|
||||
style:
|
||||
TextStyle(color: AppColors.darkNavy))),
|
||||
style: TextStyle(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurface))),
|
||||
],
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
@@ -171,12 +197,7 @@ class _CategoryManagementScreenState extends State<CategoryManagementScreen> {
|
||||
const SizedBox(height: 16),
|
||||
ElevatedButton(
|
||||
onPressed: _addCategory,
|
||||
child: const Text(
|
||||
'카테고리 추가',
|
||||
style: TextStyle(
|
||||
color: AppColors.pureWhite,
|
||||
),
|
||||
),
|
||||
child: const Text('카테고리 추가'),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -201,8 +222,8 @@ class _CategoryManagementScreenState extends State<CategoryManagementScreen> {
|
||||
title: Text(
|
||||
provider.getLocalizedCategoryName(
|
||||
context, category.name),
|
||||
style: const TextStyle(
|
||||
color: AppColors.darkNavy,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
trailing: IconButton(
|
||||
|
||||
@@ -7,7 +7,7 @@ import '../widgets/detail/detail_form_section.dart';
|
||||
import '../widgets/detail/detail_event_section.dart';
|
||||
import '../widgets/detail/detail_url_section.dart';
|
||||
import '../widgets/detail/detail_action_buttons.dart';
|
||||
import '../theme/app_colors.dart';
|
||||
// import '../theme/app_colors.dart';
|
||||
import '../l10n/app_localizations.dart';
|
||||
|
||||
/// 구독 상세 정보를 표시하고 편집할 수 있는 화면
|
||||
@@ -50,7 +50,7 @@ class _DetailScreenState extends State<DetailScreen>
|
||||
return ChangeNotifierProvider<DetailScreenController>.value(
|
||||
value: _controller,
|
||||
child: Scaffold(
|
||||
backgroundColor: AppColors.backgroundColor,
|
||||
backgroundColor: Theme.of(context).colorScheme.surface,
|
||||
body: CustomScrollView(
|
||||
controller: _controller.scrollController,
|
||||
slivers: [
|
||||
@@ -77,17 +77,16 @@ class _DetailScreenState extends State<DetailScreen>
|
||||
vertical: 12,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
baseColor.withValues(alpha: 0.15),
|
||||
baseColor.withValues(alpha: 0.08),
|
||||
],
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
),
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.surfaceContainerHighest
|
||||
.withValues(alpha: 0.4),
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
border: Border.all(
|
||||
color: baseColor.withValues(alpha: 0.2),
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.outline
|
||||
.withValues(alpha: 0.3),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
@@ -111,9 +110,9 @@ class _DetailScreenState extends State<DetailScreen>
|
||||
Text(
|
||||
AppLocalizations.of(context)
|
||||
.changesAppliedAfterSave,
|
||||
style: const TextStyle(
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: AppColors.darkNavy,
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -3,7 +3,8 @@ import 'package:flutter/services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../providers/app_lock_provider.dart';
|
||||
import '../providers/navigation_provider.dart';
|
||||
import '../theme/app_colors.dart';
|
||||
// import '../theme/app_colors.dart';
|
||||
import '../theme/color_scheme_ext.dart';
|
||||
import '../routes/app_routes.dart';
|
||||
import 'analysis_screen.dart';
|
||||
import 'app_lock_screen.dart';
|
||||
@@ -11,7 +12,6 @@ import 'settings_screen.dart';
|
||||
import 'sms_scan_screen.dart';
|
||||
import '../utils/animation_controller_helper.dart';
|
||||
import '../widgets/floating_navigation_bar.dart';
|
||||
import '../widgets/glassmorphic_scaffold.dart';
|
||||
import '../widgets/home_content.dart';
|
||||
import '../l10n/app_localizations.dart';
|
||||
import '../utils/platform_helper.dart';
|
||||
@@ -162,33 +162,34 @@ class _MainScreenState extends State<MainScreen>
|
||||
if (result == true) {
|
||||
// 상단에 스낵바 표시
|
||||
if (!context.mounted) return;
|
||||
final cs = Theme.of(context).colorScheme;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Row(
|
||||
children: [
|
||||
const Icon(
|
||||
Icon(
|
||||
Icons.check_circle,
|
||||
color: AppColors.pureWhite,
|
||||
color: cs.onPrimary,
|
||||
size: 20,
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Text(
|
||||
AppLocalizations.of(context).subscriptionAdded,
|
||||
style: const TextStyle(
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: AppColors.pureWhite,
|
||||
color: cs.onPrimary,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
backgroundColor: AppColors.successColor,
|
||||
backgroundColor: cs.success,
|
||||
behavior: SnackBarBehavior.floating,
|
||||
margin: EdgeInsets.only(
|
||||
top: MediaQuery.of(context).padding.top + 8, // 더 상단으로
|
||||
top: MediaQuery.of(context).padding.top + 8,
|
||||
left: 16,
|
||||
right: 16,
|
||||
bottom: MediaQuery.of(context).size.height - 100, // 더 상단으로
|
||||
bottom: MediaQuery.of(context).size.height - 100,
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
@@ -223,8 +224,7 @@ class _MainScreenState extends State<MainScreen>
|
||||
Widget build(BuildContext context) {
|
||||
final navigationProvider = context.watch<NavigationProvider>();
|
||||
|
||||
// 메인 그라데이션 사용
|
||||
List<Color> backgroundGradient = AppColors.mainGradient;
|
||||
// 그라데이션 제거: 단색 배경 사용
|
||||
|
||||
// 현재 인덱스가 유효한지 확인
|
||||
int currentIndex = navigationProvider.currentIndex;
|
||||
@@ -232,25 +232,31 @@ class _MainScreenState extends State<MainScreen>
|
||||
currentIndex = 0; // 추가 버튼은 홈으로 표시
|
||||
}
|
||||
|
||||
return GlassmorphicScaffold(
|
||||
body: IndexedStack(
|
||||
index: PlatformHelper.isIOS
|
||||
? (currentIndex == 3 ? 3 : currentIndex) // iOS: 설정화면은 인덱스 3
|
||||
: (currentIndex == 3
|
||||
? 3
|
||||
: currentIndex == 4
|
||||
? 4
|
||||
: currentIndex), // Android: 기존 로직
|
||||
children: _screens,
|
||||
),
|
||||
backgroundGradient: backgroundGradient,
|
||||
useFloatingNavBar: true,
|
||||
floatingNavBarIndex: navigationProvider.currentIndex,
|
||||
onFloatingNavBarTapped: (index) {
|
||||
_handleNavigation(index, context);
|
||||
},
|
||||
enableParticles: false,
|
||||
enableWaveAnimation: false,
|
||||
return Stack(
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: Container(color: Theme.of(context).colorScheme.surface),
|
||||
),
|
||||
Scaffold(
|
||||
extendBody: true,
|
||||
extendBodyBehindAppBar: true,
|
||||
body: IndexedStack(
|
||||
index: PlatformHelper.isIOS
|
||||
? (currentIndex == 3 ? 3 : currentIndex) // iOS: 설정화면은 인덱스 3
|
||||
: (currentIndex == 3
|
||||
? 3
|
||||
: currentIndex == 4
|
||||
? 4
|
||||
: currentIndex), // Android: 기존 로직
|
||||
children: _screens,
|
||||
),
|
||||
),
|
||||
FloatingNavigationBar(
|
||||
selectedIndex: navigationProvider.currentIndex,
|
||||
isVisible: true,
|
||||
onItemTapped: (index) => _handleNavigation(index, context),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:permission_handler/permission_handler.dart' as permission;
|
||||
import '../theme/app_colors.dart';
|
||||
import '../widgets/glassmorphism_card.dart';
|
||||
// Material colors only
|
||||
// Glass 제거: Material 3 Card 사용
|
||||
import '../routes/app_routes.dart';
|
||||
import '../l10n/app_localizations.dart';
|
||||
import '../services/sms_service.dart';
|
||||
@@ -92,12 +92,13 @@ class _SmsPermissionScreenState extends State<SmsPermissionScreen> {
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(Icons.sms, size: 64, color: AppColors.primaryColor),
|
||||
Icon(Icons.sms,
|
||||
size: 64, color: Theme.of(context).colorScheme.primary),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
loc.smsPermissionTitle,
|
||||
style: Theme.of(context).textTheme.headlineSmall?.copyWith(
|
||||
color: AppColors.textPrimary,
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
@@ -105,24 +106,39 @@ class _SmsPermissionScreenState extends State<SmsPermissionScreen> {
|
||||
Text(
|
||||
loc.smsPermissionRequired,
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(color: AppColors.textSecondary),
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
GlassmorphismCard(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(loc.smsPermissionReasonTitle,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold)),
|
||||
const SizedBox(height: 8),
|
||||
Text(loc.smsPermissionReasonBody),
|
||||
const SizedBox(height: 12),
|
||||
Text(loc.smsPermissionScopeTitle,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold)),
|
||||
const SizedBox(height: 8),
|
||||
Text(loc.smsPermissionScopeBody),
|
||||
],
|
||||
Card(
|
||||
elevation: 1,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
side: BorderSide(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.outline
|
||||
.withValues(alpha: 0.5),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(loc.smsPermissionReasonTitle,
|
||||
style:
|
||||
const TextStyle(fontWeight: FontWeight.bold)),
|
||||
const SizedBox(height: 8),
|
||||
Text(loc.smsPermissionReasonBody),
|
||||
const SizedBox(height: 12),
|
||||
Text(loc.smsPermissionScopeTitle,
|
||||
style:
|
||||
const TextStyle(fontWeight: FontWeight.bold)),
|
||||
const SizedBox(height: 8),
|
||||
Text(loc.smsPermissionScopeBody),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'dart:async';
|
||||
import 'dart:ui';
|
||||
import 'package:flutter/material.dart';
|
||||
import '../theme/app_colors.dart';
|
||||
// import '../theme/app_colors.dart';
|
||||
import '../services/sms_service.dart';
|
||||
import '../utils/platform_helper.dart';
|
||||
import '../routes/app_routes.dart';
|
||||
@@ -90,8 +90,6 @@ class _SplashScreenState extends State<SplashScreen>
|
||||
(reduced ? 1200 : 2000); // 축소 시 더 짧게
|
||||
final delay = (random % 10) / 10 * 2000; // 0-2초 사이의 지연시간
|
||||
|
||||
int colorIndex = (random + i) % AppColors.blueGradient.length;
|
||||
|
||||
_particles.add({
|
||||
'size': size,
|
||||
'x': x,
|
||||
@@ -99,7 +97,7 @@ class _SplashScreenState extends State<SplashScreen>
|
||||
'opacity': opacity,
|
||||
'duration': duration,
|
||||
'delay': delay,
|
||||
'color': AppColors.blueGradient[colorIndex],
|
||||
// color computed at render from ColorScheme.primary
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -137,23 +135,15 @@ class _SplashScreenState extends State<SplashScreen>
|
||||
return Scaffold(
|
||||
body: Stack(
|
||||
children: [
|
||||
// 배경 그라디언트
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [
|
||||
AppColors.dayGradient[0],
|
||||
AppColors.dayGradient[1],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
// 단색 배경
|
||||
Container(color: Theme.of(context).colorScheme.surface),
|
||||
// 글래스모피즘 오버레이
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.pureWhite.withValues(alpha: 0.05),
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurface
|
||||
.withValues(alpha: 0.05),
|
||||
),
|
||||
),
|
||||
Stack(
|
||||
@@ -180,11 +170,14 @@ class _SplashScreenState extends State<SplashScreen>
|
||||
width: particle['size'],
|
||||
height: particle['size'],
|
||||
decoration: BoxDecoration(
|
||||
color: particle['color'],
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
shape: BoxShape.circle,
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: particle['color'].withValues(alpha: 0.3),
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.primary
|
||||
.withValues(alpha: 0.3),
|
||||
blurRadius: 10,
|
||||
spreadRadius: 1,
|
||||
),
|
||||
@@ -195,43 +188,23 @@ class _SplashScreenState extends State<SplashScreen>
|
||||
);
|
||||
}).toList(),
|
||||
|
||||
// 상단 원형 그라데이션
|
||||
// 상단 원형 장식 제거(단색 배경 유지)
|
||||
Positioned(
|
||||
top: -size.height * 0.2,
|
||||
right: -size.width * 0.2,
|
||||
child: Container(
|
||||
child: SizedBox(
|
||||
width: size.width * 0.8,
|
||||
height: size.width * 0.8,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
gradient: RadialGradient(
|
||||
colors: [
|
||||
AppColors.pureWhite.withValues(alpha: 0.1),
|
||||
AppColors.pureWhite.withValues(alpha: 0.0),
|
||||
],
|
||||
stops: const [0.2, 1.0],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// 하단 원형 그라데이션
|
||||
// 하단 원형 장식 제거
|
||||
Positioned(
|
||||
bottom: -size.height * 0.1,
|
||||
left: -size.width * 0.3,
|
||||
child: Container(
|
||||
child: SizedBox(
|
||||
width: size.width * 0.9,
|
||||
height: size.width * 0.9,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
gradient: RadialGradient(
|
||||
colors: [
|
||||
AppColors.pureWhite.withValues(alpha: 0.07),
|
||||
AppColors.pureWhite.withValues(alpha: 0.0),
|
||||
],
|
||||
stops: const [0.4, 1.0],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -271,62 +244,32 @@ class _SplashScreenState extends State<SplashScreen>
|
||||
reduced: 8)),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
colors: [
|
||||
AppColors.pureWhite
|
||||
.withValues(alpha: 0.2),
|
||||
AppColors.pureWhite
|
||||
.withValues(alpha: 0.1),
|
||||
],
|
||||
),
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.surface
|
||||
.withValues(alpha: 0.6),
|
||||
borderRadius:
|
||||
BorderRadius.circular(30),
|
||||
border: Border.all(
|
||||
color: AppColors.pureWhite
|
||||
.withValues(alpha: 0.3),
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.outline
|
||||
.withValues(alpha: 0.2),
|
||||
width: 1.5,
|
||||
),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color:
|
||||
AppColors.shadowBlack,
|
||||
spreadRadius: 0,
|
||||
blurRadius:
|
||||
ReduceMotion.scale(
|
||||
context,
|
||||
normal: 30,
|
||||
reduced: 12),
|
||||
offset: const Offset(0, 10),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Center(
|
||||
child: AnimatedBuilder(
|
||||
animation:
|
||||
_animationController,
|
||||
builder: (context, _) {
|
||||
return ShaderMask(
|
||||
blendMode:
|
||||
BlendMode.srcIn,
|
||||
shaderCallback: (bounds) =>
|
||||
const LinearGradient(
|
||||
colors: AppColors
|
||||
.blueGradient,
|
||||
begin:
|
||||
Alignment.topLeft,
|
||||
end: Alignment
|
||||
.bottomRight,
|
||||
).createShader(bounds),
|
||||
child: Icon(
|
||||
Icons
|
||||
.subscriptions_outlined,
|
||||
size: 64,
|
||||
color:
|
||||
Theme.of(context)
|
||||
.primaryColor,
|
||||
),
|
||||
return Icon(
|
||||
Icons
|
||||
.subscriptions_outlined,
|
||||
size: 64,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.primary,
|
||||
);
|
||||
}),
|
||||
),
|
||||
@@ -356,7 +299,9 @@ class _SplashScreenState extends State<SplashScreen>
|
||||
style: TextStyle(
|
||||
fontSize: 36,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: AppColors.primaryColor
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.primary
|
||||
.withValues(alpha: 0.9),
|
||||
letterSpacing: 1.2,
|
||||
),
|
||||
@@ -382,7 +327,9 @@ class _SplashScreenState extends State<SplashScreen>
|
||||
AppLocalizations.of(context).appSubtitle,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
color: AppColors.primaryColor
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.primary
|
||||
.withValues(alpha: 0.7),
|
||||
letterSpacing: 0.5,
|
||||
),
|
||||
@@ -404,18 +351,22 @@ class _SplashScreenState extends State<SplashScreen>
|
||||
height: 60,
|
||||
padding: const EdgeInsets.all(6),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.pureWhite
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurface
|
||||
.withValues(alpha: 0.1),
|
||||
borderRadius: BorderRadius.circular(50),
|
||||
border: Border.all(
|
||||
color: AppColors.pureWhite
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurface
|
||||
.withValues(alpha: 0.2),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
child: const CircularProgressIndicator(
|
||||
valueColor: AlwaysStoppedAnimation<Color>(
|
||||
AppColors.pureWhite),
|
||||
child: CircularProgressIndicator(
|
||||
color:
|
||||
Theme.of(context).colorScheme.primary,
|
||||
strokeWidth: 3,
|
||||
),
|
||||
),
|
||||
@@ -436,7 +387,10 @@ class _SplashScreenState extends State<SplashScreen>
|
||||
'© 2025 NatureBridgeAI. All rights reserved.',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: AppColors.pureWhite.withValues(alpha: 0.6),
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSurface
|
||||
.withValues(alpha: 0.6),
|
||||
letterSpacing: 0.5,
|
||||
),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user