feat: EdgeToEdge 개선 - 시스템 바 색상 통일 및 화면 공간 최적화 (v1.9.0)

- MainScreen.kt: 불필요한 windowInsetsPadding 제거로 화면 공간 확보
- DealListScreen.kt: TopAppBar에 statusBarsPadding 적용, FAB에 navigationBarsPadding 적용
- Theme.kt: 시스템 바 색상을 앱 surface 색상과 일치시켜 이질감 해소
- MainActivity.kt: setupEdgeToEdge 함수 간소화 및 중복 코드 제거
- version.json: 1.9.0 버전 업데이트
This commit is contained in:
sanjeok77
2026-03-07 03:59:45 +09:00
parent bf2084626b
commit 2ab9557736
6 changed files with 166 additions and 149 deletions

View File

@@ -24,8 +24,8 @@ android {
applicationId = "com.hotdeal.alarm"
minSdk = 31
targetSdk = 35
versionCode = 14
versionName = "1.8.0"
versionCode = 15
versionName = "1.9.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {

View File

@@ -130,11 +130,13 @@ fun DealListScreen(
)
}
},
colors = TopAppBarDefaults.topAppBarColors(
containerColor = MaterialTheme.colorScheme.surface
)
)
},
colors = TopAppBarDefaults.topAppBarColors(
containerColor = MaterialTheme.colorScheme.surface,
scrolledContainerColor = MaterialTheme.colorScheme.surface
),
modifier = Modifier.statusBarsPadding()
)
},
floatingActionButton = {
AnimatedVisibility(
visible = showScrollToTop,
@@ -148,7 +150,7 @@ fun DealListScreen(
containerColor = MaterialTheme.colorScheme.primary,
contentColor = MaterialTheme.colorScheme.onPrimary,
shape = CircleShape,
modifier = Modifier.padding(bottom = 80.dp) // 메뉴키에 가려지지 않도록 상단으로 이동
modifier = Modifier.navigationBarsPadding()
) {
Icon(
imageVector = Icons.Filled.KeyboardArrowUp,
@@ -396,10 +398,10 @@ fun DealListScreen(
}
}
// EdgeToEdge: 하단 네비게이션 바 공간 확보
item {
Spacer(modifier = Modifier.height(32.dp))
}
// EdgeToEdge: 하단 네비게이션 바 공간 확보
item {
Spacer(modifier = Modifier.height(16.dp))
}
}
}
}

View File

@@ -133,22 +133,13 @@ class MainActivity : ComponentActivity() {
* EdgeToEdge 설정 - One UI 7+ 대응
*/
private fun setupEdgeToEdge() {
// WindowCompat을 사용한 설정
// WindowCompat을 사용한 EdgeToEdge 설정
WindowCompat.setDecorFitsSystemWindows(window, false)
// statusBarColor와 navigationBarColor를 투명하게
window.statusBarColor = android.graphics.Color.TRANSPARENT
window.navigationBarColor = android.graphics.Color.TRANSPARENT
// One UI 7+에서 시스템 바가 콘텐츠를 가리지 않도록 설정
// One UI 7+에서 시스템 바 인셋 처리
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) {
window.setDecorFitsSystemWindows(false)
// 시스템 바 인셋 처리
ViewCompat.setOnApplyWindowInsetsListener(window.decorView.rootView) { view, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
val ime = insets.getInsets(WindowInsetsCompat.Type.ime())
view.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
@@ -159,29 +150,8 @@ class MainActivity : ComponentActivity() {
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
)
}
// 시스템 바 아이콘 색상 설정 (라이트/다크 모드)
val decorView = window.decorView
@Suppress("DEPRECATION")
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) {
window.insetsController?.let { controller ->
// 상태바 아이콘 밝게 (다크 모드용)
controller.setSystemBarsAppearance(
0,
android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS
)
// 네비게이션바 아이콘 밝게 (다크 모드용)
controller.setSystemBarsAppearance(
0,
android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS
)
}
} else {
@Suppress("DEPRECATION")
decorView.systemUiVisibility = decorView.systemUiVisibility or
View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR or
View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
}
// 시스템 바 아이콘 색상 설정은 Theme.kt에서 처리
}
override fun onDestroy() {

View File

@@ -67,9 +67,7 @@ fun MainScreen(
}
Column(
modifier = Modifier
.fillMaxSize()
.windowInsetsPadding(WindowInsets.safeDrawing) // 시스템 바 패딩 적용
modifier = Modifier.fillMaxSize()
) {
HorizontalPager(
state = pagerState,

View File

@@ -17,109 +17,110 @@ import androidx.compose.ui.platform.LocalView
import androidx.core.view.WindowCompat
import com.hotdeal.alarm.domain.model.SiteType
// Light Theme Colors
private val LightPrimary = Color(0xFF1976D2)
// ============================================
// Material You Style - Premium Color Palette
// ============================================
// Light Theme - Premium Palette
private val LightPrimary = Color(0xFF0061A4)
private val LightOnPrimary = Color(0xFFFFFFFF)
private val LightPrimaryContainer = Color(0xFFD1E4FF)
private val LightOnPrimaryContainer = Color(0xFF001D36)
private val LightSecondary = Color(0xFFFF9800)
private val LightSecondary = Color(0xFF535F70)
private val LightOnSecondary = Color(0xFFFFFFFF)
private val LightSecondaryContainer = Color(0xFFFFE0B2)
private val LightOnSecondaryContainer = Color(0xFF261800)
private val LightSecondaryContainer = Color(0xFFD7E3F8)
private val LightOnSecondaryContainer = Color(0xFF101C2B)
private val LightTertiary = Color(0xFF536DFE)
private val LightTertiary = Color(0xFF6B5778)
private val LightOnTertiary = Color(0xFFFFFFFF)
private val LightTertiaryContainer = Color(0xFFF2DAFF)
private val LightOnTertiaryContainer = Color(0xFF251431)
private val LightBackground = Color(0xFFFAFAFA)
private val LightOnBackground = Color(0xFF1C1B1F)
private val LightSurface = Color(0xFFFFFFFF)
private val LightOnSurface = Color(0xFF1C1B1F)
private val LightBackground = Color(0xFFFDFCFF)
private val LightOnBackground = Color(0xFF1A1C1E)
private val LightSurface = Color(0xFFFDFCFF)
private val LightOnSurface = Color(0xFF1A1C1E)
private val LightSurfaceVariant = Color(0xFFDFE2EB)
private val LightOnSurfaceVariant = Color(0xFF43474E)
private val LightError = Color(0xFFD32F2F)
private val LightError = Color(0xFFBA1A1A)
private val LightOnError = Color(0xFFFFFFFF)
private val LightErrorContainer = Color(0xFFFFDAD6)
private val LightOnErrorContainer = Color(0xFF410002)
private val LightOutline = Color(0xFF79747E)
private val LightOutlineVariant = Color(0xFFCAC4D0)
private val LightOutline = Color(0xFF73777F)
private val LightOutlineVariant = Color(0xFFC3C6CF)
private val LightInverseSurface = Color(0xFF2F3033)
private val LightInverseOnSurface = Color(0xFFF1F0F4)
private val LightInversePrimary = Color(0xFF9ECAFF)
private val LightSurfaceTint = Color(0xFF0061A4)
// Dark Theme Colors
private val DarkPrimary = Color(0xFF90CAF9)
// Dark Theme - Premium Palette
private val DarkPrimary = Color(0xFF9ECAFF)
private val DarkOnPrimary = Color(0xFF003258)
private val DarkPrimaryContainer = Color(0xFF00497D)
private val DarkOnPrimaryContainer = Color(0xFFD1E4FF)
private val DarkSecondary = Color(0xFFFFB74D)
private val DarkOnSecondary = Color(0xFF442B00)
private val DarkSecondaryContainer = Color(0xFF624000)
private val DarkOnSecondaryContainer = Color(0xFFFFE0B2)
private val DarkSecondary = Color(0xFFBBC7DB)
private val DarkOnSecondary = Color(0xFF253140)
private val DarkSecondaryContainer = Color(0xFF3B4858)
private val DarkOnSecondaryContainer = Color(0xFFD7E3F8)
private val DarkTertiary = Color(0xFF8C9EFF)
private val DarkOnTertiary = Color(0xFF001A3F)
private val DarkTertiary = Color(0xFFD6BEE4)
private val DarkOnTertiary = Color(0xFF3B2948)
private val DarkTertiaryContainer = Color(0xFF523F5F)
private val DarkOnTertiaryContainer = Color(0xFFF2DAFF)
private val DarkBackground = Color(0xFF121212)
private val DarkOnBackground = Color(0xFFE0E0E0)
private val DarkSurface = Color(0xFF1E1E1E)
private val DarkOnSurface = Color(0xFFE0E0E0)
private val DarkBackground = Color(0xFF1A1C1E)
private val DarkOnBackground = Color(0xFFE2E2E6)
private val DarkSurface = Color(0xFF1A1C1E)
private val DarkOnSurface = Color(0xFFE2E2E6)
private val DarkSurfaceVariant = Color(0xFF43474E)
private val DarkOnSurfaceVariant = Color(0xFFC3C6CF)
private val DarkError = Color(0xFFCF6679)
private val DarkOnError = Color(0xFF000000)
private val DarkError = Color(0xFFFFB4AB)
private val DarkOnError = Color(0xFF690005)
private val DarkErrorContainer = Color(0xFF93000A)
private val DarkOnErrorContainer = Color(0xFFFFDAD6)
private val DarkOutline = Color(0xFF938F99)
private val DarkOutlineVariant = Color(0xFF49454F)
private val DarkOutline = Color(0xFF8D9199)
private val DarkOutlineVariant = Color(0xFF43474E)
private val DarkInverseSurface = Color(0xFFE2E2E6)
private val DarkInverseOnSurface = Color(0xFF2F3033)
private val DarkInversePrimary = Color(0xFF0061A4)
private val DarkSurfaceTint = Color(0xFF9ECAFF)
// =========================
// index.html Inspired Colors
// =========================
// ============================================
// Site Colors - Premium Tones
// ============================================
// Dark Theme (index.html style)
val IndexBgPrimary = Color(0xFF0f0f1a)
val IndexBgSecondary = Color(0xFF1a1a2e)
val IndexBgCard = Color(0xFF16162a)
val IndexBgCardHover = Color(0xFF1e1e3a)
val IndexBgInput = Color(0xFF252545)
val IndexTextPrimary = Color(0xFFffffff)
val IndexTextSecondary = Color(0xFFa0a0b8)
val IndexTextMuted = Color(0xFF6b6b8a)
val IndexAccentPrimary = Color(0xFF6366f1)
val IndexAccentSecondary = Color(0xFF8b5cf6)
val IndexHotBadgeBg = Color(0x26EF4444) // rgba(239, 68, 68, 0.15)
val IndexHotBadgeText = Color(0xFFef4444)
val IndexBoardBadgeBg = Color(0x26818CF8) // rgba(129, 140, 248, 0.15)
val IndexBoardBadgeText = Color(0xFF818cf8)
// Light Theme (index.html style)
val IndexLightBgPrimary = Color(0xFFf8fafc)
val IndexLightBgSecondary = Color(0xFFffffff)
val IndexLightBgCard = Color(0xFFffffff)
val IndexLightBgCardHover = Color(0xFFf1f5f9)
val IndexLightBgInput = Color(0xFFf1f5f9)
val IndexLightTextPrimary = Color(0xFF0f172a)
val IndexLightTextSecondary = Color(0xFF475569)
val IndexLightTextMuted = Color(0xFF94a3b8)
val IndexLightAccentPrimary = Color(0xFF4f46e5)
val IndexLightAccentSecondary = Color(0xFF7c3aed)
val IndexLightHotBadgeBg = Color(0x1ADC2626) // rgba(220, 38, 38, 0.1)
val IndexLightHotBadgeText = Color(0xFFdc2626)
val IndexLightBoardBadgeBg = Color(0x1A4F46E5) // rgba(79, 70, 229, 0.1)
val IndexLightBoardBadgeText = Color(0xFF4f46e5)
// Site Colors
// 뽐뿌 - Premium Pink
val PpomppuColor = Color(0xFFE91E63)
val ClienColor = Color(0xFF4CAF50)
val RuriwebColor = Color(0xFF2196F3)
val CoolenjoyColor = Color(0xFFFF5722)
val PpomppuColorLight = Color(0xFFFCE4EC)
val PpomppuColorDark = Color(0xFFC2185B)
// 클리앙 - Premium Green
val ClienColor = Color(0xFF2E7D32)
val ClienColorLight = Color(0xFFE8F5E9)
val ClienColorDark = Color(0xFF1B5E20)
// 루리웹 - Premium Blue
val RuriwebColor = Color(0xFF1565C0)
val RuriwebColorLight = Color(0xFFE3F2FD)
val RuriwebColorDark = Color(0xFF0D47A1)
// 쿨엔조이 - Premium Orange
val CoolenjoyColor = Color(0xFFEF6C00)
val CoolenjoyColorLight = Color(0xFFFFF3E0)
val CoolenjoyColorDark = Color(0xFFE65100)
// Keyword Match - Light Red Theme
val KeywordMatchColor = Color(0xFFE53935)
val KeywordMatchColorLight = Color(0xFFFFEBEE)
// Favorite - Premium Red
val FavoriteColor = Color(0xFFE53935)
/**
* 사이트별 색상 가져오기
@@ -134,6 +135,36 @@ fun getSiteColor(siteType: SiteType?): Color {
}
}
/**
* 사이트별 라이트 배경색 가져오기
*/
fun getSiteColorLight(siteType: SiteType?): Color {
return when (siteType) {
SiteType.PPOMPPU -> PpomppuColorLight
SiteType.CLIEN -> ClienColorLight
SiteType.RURIWEB -> RuriwebColorLight
SiteType.COOLENJOY -> CoolenjoyColorLight
null -> Color.LightGray.copy(alpha = 0.3f)
}
}
/**
* 사이트별 다크 배경색 가져오기
*/
fun getSiteColorDark(siteType: SiteType?): Color {
return when (siteType) {
SiteType.PPOMPPU -> PpomppuColorDark
SiteType.CLIEN -> ClienColorDark
SiteType.RURIWEB -> RuriwebColorDark
SiteType.COOLENJOY -> CoolenjoyColorDark
null -> Color.DarkGray
}
}
// ============================================
// Color Schemes
// ============================================
private val LightColorScheme = lightColorScheme(
primary = LightPrimary,
onPrimary = LightOnPrimary,
@@ -145,16 +176,24 @@ private val LightColorScheme = lightColorScheme(
onSecondaryContainer = LightOnSecondaryContainer,
tertiary = LightTertiary,
onTertiary = LightOnTertiary,
tertiaryContainer = LightTertiaryContainer,
onTertiaryContainer = LightOnTertiaryContainer,
background = LightBackground,
onBackground = LightOnBackground,
surface = LightSurface,
onSurface = LightOnSurface,
surfaceVariant = LightSurfaceVariant,
onSurfaceVariant = LightOnSurfaceVariant,
error = LightError,
onError = LightOnError,
errorContainer = LightErrorContainer,
onErrorContainer = LightOnErrorContainer,
outline = LightOutline,
outlineVariant = LightOutlineVariant
outlineVariant = LightOutlineVariant,
inverseSurface = LightInverseSurface,
inverseOnSurface = LightInverseOnSurface,
inversePrimary = LightInversePrimary,
surfaceTint = LightSurfaceTint
)
private val DarkColorScheme = darkColorScheme(
@@ -168,16 +207,24 @@ private val DarkColorScheme = darkColorScheme(
onSecondaryContainer = DarkOnSecondaryContainer,
tertiary = DarkTertiary,
onTertiary = DarkOnTertiary,
tertiaryContainer = DarkTertiaryContainer,
onTertiaryContainer = DarkOnTertiaryContainer,
background = DarkBackground,
onBackground = DarkOnBackground,
surface = DarkSurface,
onSurface = DarkOnSurface,
surfaceVariant = DarkSurfaceVariant,
onSurfaceVariant = DarkOnSurfaceVariant,
error = DarkError,
onError = DarkOnError,
errorContainer = DarkErrorContainer,
onErrorContainer = DarkOnErrorContainer,
outline = DarkOutline,
outlineVariant = DarkOutlineVariant
outlineVariant = DarkOutlineVariant,
inverseSurface = DarkInverseSurface,
inverseOnSurface = DarkInverseOnSurface,
inversePrimary = DarkInversePrimary,
surfaceTint = DarkSurfaceTint
)
@Composable
@@ -197,19 +244,19 @@ fun HotDealTheme(
val view = LocalView.current
if (!view.isInEditMode) {
SideEffect {
val window = (view.context as Activity).window
// Edge-to-edge: 투명한 상태바
window.statusBarColor = android.graphics.Color.TRANSPARENT
window.navigationBarColor = android.graphics.Color.TRANSPARENT
WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = !darkTheme
WindowCompat.getInsetsController(window, view).isAppearanceLightNavigationBars = !darkTheme
}
SideEffect {
val window = (view.context as Activity).window
// 시스템 바 색상을 앱 배경색과 일치시켜 이질감 제거
window.statusBarColor = colorScheme.surface.toArgb()
window.navigationBarColor = colorScheme.surface.toArgb()
WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = !darkTheme
WindowCompat.getInsetsController(window, view).isAppearanceLightNavigationBars = !darkTheme
}
}
MaterialTheme(
colorScheme = colorScheme,
typography = AppTypography,
content = content
)
}
}
MaterialTheme(
colorScheme = colorScheme,
typography = AppTypography,
content = content
)
}

View File

@@ -1,14 +1,14 @@
{
"version": "1.6.0",
"versionCode": 12,
"version": "1.9.0",
"versionCode": 15,
"minSdk": 31,
"targetSdk": 35,
"forceUpdate": false,
"updateUrl": "https://git.webpluss.net/attachments/0482dc08-5216-4223-beda-2887501578d8",
"changelog": [
"Pull to Refresh 기능 추가 (아래로 당겨서 새로고침)",
"EdgeToEdge 개선 (투명 상태바/네비게이션바)",
"출처를 알 수 없는 앱 설치 권한 추가",
"WindowInsets 처리 개선"
"EdgeToEdge 색상 개선 - 시스템 바가 앱 테마와 일치",
"화면 공간 최적화 - 불필요한 패딩 제거",
"TopAppBar가 시스템 바 영역까지 확장",
"하단 네비게이션 영역 패딩 최적화"
]
}