Skip to content

Commit af718ac

Browse files
authored
Merge pull request #96 from YAPP-Github/fix/bottom
[Fix/#95] 바텀 네비게이션 바, 스낵바 패딩, status bar 색상 설정
2 parents df5e433 + 845f5ae commit af718ac

File tree

7 files changed

+188
-33
lines changed

7 files changed

+188
-33
lines changed

core/auth/src/main/java/com/yapp/breake/core/auth/kakao/KakaoAuthScreen.kt

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.yapp.breake.core.auth.kakao
22

33
import android.annotation.SuppressLint
4+
import android.app.Activity
45
import android.content.Intent
56
import android.view.ViewGroup.LayoutParams
67
import android.webkit.WebResourceError
@@ -9,16 +10,18 @@ import android.webkit.WebView
910
import android.webkit.WebViewClient
1011
import androidx.activity.compose.BackHandler
1112
import androidx.compose.foundation.layout.fillMaxSize
12-
import androidx.compose.foundation.layout.statusBarsPadding
1313
import androidx.compose.runtime.Composable
14+
import androidx.compose.runtime.DisposableEffect
1415
import androidx.compose.runtime.getValue
1516
import androidx.compose.runtime.mutableStateOf
1617
import androidx.compose.runtime.remember
1718
import androidx.compose.runtime.setValue
1819
import androidx.compose.ui.Modifier
1920
import androidx.compose.ui.platform.LocalContext
21+
import androidx.compose.ui.platform.LocalView
2022
import androidx.compose.ui.viewinterop.AndroidView
2123
import androidx.core.net.toUri
24+
import androidx.core.view.WindowInsetsControllerCompat
2225
import com.yapp.breake.core.auth.BuildConfig
2326
import com.yapp.breake.core.auth.R
2427
import timber.log.Timber
@@ -71,6 +74,24 @@ fun KakaoScreen(
7174
}
7275
}
7376

77+
val view = LocalView.current
78+
79+
DisposableEffect(view) {
80+
val window = (view.context as? Activity)?.window ?: return@DisposableEffect onDispose {}
81+
val insetsController = WindowInsetsControllerCompat(window, view)
82+
83+
// 원래 설정 저장
84+
val originalLightStatusBars = insetsController.isAppearanceLightStatusBars
85+
86+
// Status Bar 아이콘을 어둡게 설정 (밝은 배경용)
87+
insetsController.isAppearanceLightStatusBars = true
88+
89+
onDispose {
90+
// 원래 설정으로 복원
91+
insetsController.isAppearanceLightStatusBars = originalLightStatusBars
92+
}
93+
}
94+
7495
val webView = WebView(context).apply {
7596
webViewRef = this
7697

@@ -185,9 +206,7 @@ fun KakaoScreen(
185206

186207
AndroidView(
187208
factory = { webView },
188-
modifier = Modifier
189-
.fillMaxSize()
190-
.statusBarsPadding(),
209+
modifier = Modifier.fillMaxSize(),
191210
onRelease = { webView ->
192211
webView.destroySafely()
193212
},

core/designsystem/src/main/java/com/yapp/breake/core/designsystem/component/Button.kt

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import androidx.compose.runtime.remember
2121
import androidx.compose.ui.Alignment
2222
import androidx.compose.ui.Modifier
2323
import androidx.compose.ui.graphics.Color
24+
import androidx.compose.ui.layout.onGloballyPositioned
25+
import androidx.compose.ui.platform.LocalDensity
2426
import androidx.compose.ui.res.painterResource
2527
import androidx.compose.ui.text.TextStyle
2628
import androidx.compose.ui.text.style.TextAlign
@@ -32,6 +34,7 @@ import com.yapp.breake.core.designsystem.theme.BrakeTheme
3234
import com.yapp.breake.core.designsystem.theme.Gray200
3335
import com.yapp.breake.core.designsystem.theme.Gray700
3436
import com.yapp.breake.core.designsystem.theme.Gray800
37+
import com.yapp.breake.core.designsystem.theme.LocalDynamicPaddings
3538
import com.yapp.breake.core.designsystem.theme.Red
3639
import com.yapp.breake.core.designsystem.util.BooleanProvider
3740
import com.yapp.breake.core.designsystem.util.MultipleEventsCutter
@@ -53,13 +56,24 @@ fun LargeButton(
5356
) {
5457
val multipleEventsCutter = remember { MultipleEventsCutter.get() }
5558

59+
val density = LocalDensity.current
60+
val dynamicPaddingsProvider = LocalDynamicPaddings.current
61+
5662
Button(
5763
shape = MaterialTheme.shapes.large,
5864
colors = colors,
5965
contentPadding = paddingValues,
6066
enabled = enabled,
6167
onClick = { multipleEventsCutter.processEvent(onClick) },
62-
modifier = modifier.fillMaxWidth(),
68+
modifier = modifier
69+
.fillMaxWidth()
70+
.onGloballyPositioned { coordinates ->
71+
with(density) {
72+
dynamicPaddingsProvider.updateOneButtonHeight(
73+
coordinates.size.height.toDp() + (24 + 12).dp,
74+
)
75+
}
76+
},
6377
) {
6478
Row(
6579
modifier = Modifier.fillMaxWidth(),
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,42 @@
11
package com.yapp.breake.core.designsystem.theme
22

33
import androidx.compose.runtime.Immutable
4+
import androidx.compose.runtime.getValue
5+
import androidx.compose.runtime.mutableStateOf
6+
import androidx.compose.runtime.setValue
47
import androidx.compose.runtime.staticCompositionLocalOf
58
import androidx.compose.ui.unit.Dp
69
import androidx.compose.ui.unit.dp
710

811
val Paddings = BrakePadding()
912

1013
val LocalPadding = staticCompositionLocalOf { BrakePadding() }
14+
val LocalDynamicPaddings = staticCompositionLocalOf { DynamicPaddingsProvider() }
1115

1216
@Immutable
1317
data class BrakePadding(
1418
val screenPaddingHorizontal: Dp = 16.dp,
1519
)
20+
21+
data class DynamicPaddings(
22+
val bottomNavBarHeight: Dp = 100.dp,
23+
val oneButtonHeight: Dp = 80.dp,
24+
val twoButtonHeight: Dp = 130.dp,
25+
)
26+
27+
class DynamicPaddingsProvider {
28+
var paddings by mutableStateOf(DynamicPaddings())
29+
private set
30+
31+
fun updateBottomNavHeight(height: Dp) {
32+
paddings = paddings.copy(bottomNavBarHeight = height)
33+
}
34+
35+
fun updateOneButtonHeight(height: Dp) {
36+
paddings = paddings.copy(oneButtonHeight = height)
37+
}
38+
39+
fun updateTwoButtonHeight(height: Dp) {
40+
paddings = paddings.copy(twoButtonHeight = height)
41+
}
42+
}

presentation/home/src/main/java/com/yapp/breake/presentation/home/screen/TickingScreen.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import com.yapp.breake.core.designsystem.theme.AppItemGradient
4141
import com.yapp.breake.core.designsystem.theme.BlockingTimerBackgroundGradient
4242
import com.yapp.breake.core.designsystem.theme.BrakeTheme
4343
import com.yapp.breake.core.designsystem.theme.Gray900
44+
import com.yapp.breake.core.designsystem.theme.LocalDynamicPaddings
4445
import com.yapp.breake.core.model.app.AppGroup
4546
import com.yapp.breake.core.model.app.AppGroupState
4647
import com.yapp.breake.presentation.home.R
@@ -90,6 +91,8 @@ internal fun TickingScreen(
9091
}
9192
}
9293

94+
val bottomPadding = LocalDynamicPaddings.current.paddings.bottomNavBarHeight
95+
9396
// LazyColumn, LazyRow 의 오버 스크롤시 내부 요소의 늘어짐 방지
9497
CompositionLocalProvider(LocalOverscrollFactory provides null) {
9598
Scaffold(
@@ -226,7 +229,7 @@ internal fun TickingScreen(
226229
}
227230
}
228231

229-
item { VerticalSpacer(12.dp) }
232+
item { VerticalSpacer(bottomPadding) }
230233
}
231234
},
232235
)

presentation/login/src/main/java/com/yapp/breake/presentation/login/LoginScreen.kt

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,14 @@ import androidx.compose.material3.Text
1313
import androidx.compose.runtime.Composable
1414
import androidx.compose.runtime.LaunchedEffect
1515
import androidx.compose.runtime.getValue
16+
import androidx.compose.runtime.mutableStateOf
17+
import androidx.compose.runtime.remember
18+
import androidx.compose.runtime.setValue
1619
import androidx.compose.ui.Alignment
1720
import androidx.compose.ui.Modifier
21+
import androidx.compose.ui.layout.onGloballyPositioned
1822
import androidx.compose.ui.platform.LocalContext
23+
import androidx.compose.ui.platform.LocalDensity
1924
import androidx.compose.ui.res.painterResource
2025
import androidx.compose.ui.res.stringResource
2126
import androidx.compose.ui.text.style.TextAlign
@@ -28,6 +33,7 @@ import com.google.android.gms.auth.api.identity.Identity
2833
import com.google.android.gms.common.api.ApiException
2934
import com.yapp.breake.core.auth.kakao.KakaoScreen
3035
import com.yapp.breake.core.designsystem.theme.BrakeTheme
36+
import com.yapp.breake.core.designsystem.theme.LocalDynamicPaddings
3137
import com.yapp.breake.core.designsystem.theme.LocalPadding
3238
import com.yapp.breake.core.navigation.compositionlocal.LocalMainAction
3339
import com.yapp.breake.core.navigation.compositionlocal.LocalNavigatorAction
@@ -157,6 +163,22 @@ fun LoginScreen(
157163
onGoogleLoginClick: () -> Unit,
158164
onkakaoLoginClick: () -> Unit,
159165
) {
166+
val density = LocalDensity.current
167+
val dynamicPaddingsProvider = LocalDynamicPaddings.current
168+
169+
var googleButtonHeight by remember { mutableStateOf(0.dp) }
170+
var kakaoButtonHeight by remember { mutableStateOf(0.dp) }
171+
172+
val buttonSpacing = 12.dp
173+
val bottomPadding = 24.dp
174+
175+
LaunchedEffect(googleButtonHeight, kakaoButtonHeight) {
176+
if (googleButtonHeight > 0.dp && kakaoButtonHeight > 0.dp) {
177+
val totalHeight = googleButtonHeight + kakaoButtonHeight + buttonSpacing + bottomPadding
178+
dynamicPaddingsProvider.updateTwoButtonHeight(totalHeight)
179+
}
180+
}
181+
160182
ConstraintLayout(
161183
modifier = Modifier.fillMaxSize(),
162184
) {
@@ -206,6 +228,9 @@ fun LoginScreen(
206228
modifier = Modifier
207229
.padding(horizontal = padding)
208230
.widthIn(max = 400.dp)
231+
.onGloballyPositioned { coordinates ->
232+
googleButtonHeight = with(density) { coordinates.size.height.toDp() }
233+
}
209234
.constrainAs(googleLoginButton) {
210235
bottom.linkTo(kakaoLoginButton.top, margin = 12.dp)
211236
start.linkTo(parent.start)
@@ -220,6 +245,9 @@ fun LoginScreen(
220245
.padding(horizontal = padding)
221246
.padding(bottom = 24.dp)
222247
.widthIn(max = 400.dp)
248+
.onGloballyPositioned { coordinates ->
249+
kakaoButtonHeight = with(density) { coordinates.size.height.toDp() }
250+
}
223251
.constrainAs(kakaoLoginButton) {
224252
bottom.linkTo(parent.bottom)
225253
start.linkTo(parent.start)

presentation/main/src/main/java/com/yapp/breake/presentation/main/MainScreen.kt

Lines changed: 87 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,31 @@
11
package com.yapp.breake.presentation.main
22

3+
import androidx.compose.foundation.background
4+
import androidx.compose.foundation.clickable
5+
import androidx.compose.foundation.interaction.MutableInteractionSource
6+
import androidx.compose.foundation.layout.Box
37
import androidx.compose.foundation.layout.WindowInsets
8+
import androidx.compose.foundation.layout.fillMaxSize
49
import androidx.compose.foundation.layout.fillMaxWidth
510
import androidx.compose.foundation.layout.navigationBarsPadding
611
import androidx.compose.foundation.layout.padding
712
import androidx.compose.foundation.layout.wrapContentWidth
813
import androidx.compose.material3.Scaffold
914
import androidx.compose.runtime.Composable
15+
import androidx.compose.runtime.CompositionLocalProvider
1016
import androidx.compose.runtime.getValue
17+
import androidx.compose.runtime.remember
1118
import androidx.compose.ui.Alignment
1219
import androidx.compose.ui.Modifier
20+
import androidx.compose.ui.graphics.Brush
21+
import androidx.compose.ui.graphics.Color
22+
import androidx.compose.ui.layout.onGloballyPositioned
23+
import androidx.compose.ui.platform.LocalDensity
1324
import androidx.compose.ui.unit.dp
1425
import androidx.lifecycle.compose.collectAsStateWithLifecycle
26+
import com.yapp.breake.core.designsystem.theme.DynamicPaddingsProvider
27+
import com.yapp.breake.core.designsystem.theme.Gray900
28+
import com.yapp.breake.core.designsystem.theme.LocalDynamicPaddings
1529
import com.yapp.breake.core.navigation.route.InitialRoute
1630
import com.yapp.breake.core.navigation.route.MainTabRoute
1731
import com.yapp.breake.presentation.main.component.BrakeSnackbar
@@ -47,32 +61,73 @@ private fun MainScreenContent(
4761
// 2. MainTabRoute 화면일 때 하단 네비게이션 바를 띄우고, 그 외는 안띄우기 위한 Route 구독
4862
val currentRoute by navigator.currentRoute.collectAsStateWithLifecycle()
4963

64+
// 바텀 패딩 조정 용도 (스낵바 높이 위치 및 하단 네비게이션 바 상호작용)
65+
val dynamicPaddingsProvider = remember { DynamicPaddingsProvider() }
66+
val density = LocalDensity.current
67+
5068
Scaffold(
5169
modifier = modifier,
5270
content = { padding ->
53-
MainNavHost(
54-
navigator = navigator,
55-
padding = padding,
56-
onChangeDarkTheme = onChangeDarkTheme,
57-
)
58-
},
59-
bottomBar = {
60-
MainBottomNavBar(
61-
modifier = Modifier
62-
.navigationBarsPadding()
63-
.fillMaxWidth()
64-
.padding(bottom = 34.dp)
65-
.wrapContentWidth(Alignment.CenterHorizontally),
66-
visible = currentRoute is MainTabRoute,
67-
tabs = MainTab.entries.toPersistentList(),
68-
currentTab = when (currentRoute) {
69-
is MainTabRoute.Home -> MainTab.HOME
70-
is MainTabRoute.Report -> MainTab.REPORT
71-
is MainTabRoute.Setting -> MainTab.SETTING
72-
else -> null
73-
},
74-
onTabSelected = navigator::navigate,
75-
)
71+
Box(
72+
modifier = Modifier.fillMaxSize(),
73+
) {
74+
CompositionLocalProvider(
75+
LocalDynamicPaddings provides dynamicPaddingsProvider,
76+
) {
77+
MainNavHost(
78+
navigator = navigator,
79+
padding = padding,
80+
onChangeDarkTheme = onChangeDarkTheme,
81+
)
82+
}
83+
84+
Box(
85+
modifier = Modifier
86+
.align(Alignment.BottomCenter)
87+
.clickable(
88+
interactionSource = remember { MutableInteractionSource() },
89+
indication = null,
90+
) { /* 터치 이벤트 가로채기 */ }
91+
.onGloballyPositioned { coordinates ->
92+
with(density) {
93+
dynamicPaddingsProvider.updateBottomNavHeight(
94+
coordinates.size.height.toDp() + 12.dp,
95+
)
96+
}
97+
}
98+
.fillMaxWidth()
99+
.background(
100+
brush = Brush.verticalGradient(
101+
colors = listOf(
102+
Color.Transparent,
103+
Gray900.copy(alpha = 0.1f),
104+
Gray900.copy(alpha = 0.3f),
105+
Gray900.copy(alpha = 0.5f),
106+
Gray900.copy(alpha = 0.8f),
107+
Gray900.copy(alpha = 0.9f),
108+
Gray900, Gray900, Gray900,
109+
),
110+
),
111+
)
112+
.wrapContentWidth(Alignment.CenterHorizontally)
113+
.navigationBarsPadding()
114+
.padding(bottom = 34.dp),
115+
) {
116+
MainBottomNavBar(
117+
modifier = Modifier
118+
.background(Color.Transparent),
119+
visible = currentRoute is MainTabRoute,
120+
tabs = MainTab.entries.toPersistentList(),
121+
currentTab = when (currentRoute) {
122+
is MainTabRoute.Home -> MainTab.HOME
123+
is MainTabRoute.Report -> MainTab.REPORT
124+
is MainTabRoute.Setting -> MainTab.SETTING
125+
else -> null
126+
},
127+
onTabSelected = navigator::navigate,
128+
)
129+
}
130+
}
76131
},
77132
contentWindowInsets = WindowInsets(0.dp),
78133
snackbarHost = {
@@ -86,17 +141,23 @@ private fun MainScreenContent(
86141
// 현재 화면에 따라 스낵바 y 축 위치 조정
87142
modifier = Modifier.then(
88143
when (currentRoute) {
89-
is MainTabRoute -> Modifier.padding(bottom = 0.dp)
144+
is MainTabRoute -> Modifier.padding(
145+
bottom = dynamicPaddingsProvider.paddings.bottomNavBarHeight,
146+
)
90147

91148
InitialRoute.Login ->
92149
Modifier
93150
.navigationBarsPadding()
94-
.padding(bottom = 130.dp) // 기존 190, 배포 환경 구성 완료 전까지 감추기
151+
.padding(
152+
bottom = dynamicPaddingsProvider.paddings.twoButtonHeight,
153+
)
95154

96155
else ->
97156
Modifier
98157
.navigationBarsPadding()
99-
.padding(bottom = 80.dp)
158+
.padding(
159+
bottom = dynamicPaddingsProvider.paddings.oneButtonHeight,
160+
)
100161
},
101162
),
102163
)

0 commit comments

Comments
 (0)