From e6f867841da4fab08b62bcef3173208082924c1b Mon Sep 17 00:00:00 2001 From: yunsehwan Date: Sun, 26 Apr 2026 20:24:28 +0900 Subject: [PATCH 1/3] =?UTF-8?q?REFACTOR:=20=EC=83=81=EB=8B=A8=20=EB=B0=94?= =?UTF-8?q?=20=EC=98=81=EC=97=AD=EC=9D=98=20=EC=83=89=EC=83=81=EC=97=90=20?= =?UTF-8?q?=EB=94=B0=EB=9D=BC=20=EC=83=81=EB=8B=A8=EB=B0=94=20=EC=95=84?= =?UTF-8?q?=EC=9D=B4=EC=BD=98=20=EC=83=89=EC=83=81=EC=9D=B4=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=EB=90=98=EB=8A=94=20=EB=A1=9C=EC=A7=81=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20=EB=B0=8F=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/threegap/bitnagil/MainNavHost.kt | 3 ++ .../bitnagil/navigation/home/HomeNavHost.kt | 10 +--- .../util/statusbar/NavStatusBarEffect.kt | 24 +++++++++ .../statusbar/StatusBarAppearanceManager.kt | 54 +++++++++++++++++++ 4 files changed, 83 insertions(+), 8 deletions(-) create mode 100644 presentation/src/main/java/com/threegap/bitnagil/presentation/util/statusbar/NavStatusBarEffect.kt create mode 100644 presentation/src/main/java/com/threegap/bitnagil/presentation/util/statusbar/StatusBarAppearanceManager.kt diff --git a/app/src/main/java/com/threegap/bitnagil/MainNavHost.kt b/app/src/main/java/com/threegap/bitnagil/MainNavHost.kt index 98911568..a8ee22fb 100644 --- a/app/src/main/java/com/threegap/bitnagil/MainNavHost.kt +++ b/app/src/main/java/com/threegap/bitnagil/MainNavHost.kt @@ -27,12 +27,15 @@ import com.threegap.bitnagil.presentation.screen.splash.SplashScreenContainer import com.threegap.bitnagil.presentation.screen.terms.TermsAgreementScreenContainer import com.threegap.bitnagil.presentation.screen.webview.BitnagilWebViewScreen import com.threegap.bitnagil.presentation.screen.withdrawal.WithdrawalScreenContainer +import com.threegap.bitnagil.presentation.util.statusbar.NavStatusBarEffect @Composable fun MainNavHost( navigator: MainNavigator, modifier: Modifier = Modifier, ) { + NavStatusBarEffect(navController = navigator.navController) + NavHost( navController = navigator.navController, startDestination = navigator.startDestination, diff --git a/app/src/main/java/com/threegap/bitnagil/navigation/home/HomeNavHost.kt b/app/src/main/java/com/threegap/bitnagil/navigation/home/HomeNavHost.kt index f90cde81..a2d10b5f 100644 --- a/app/src/main/java/com/threegap/bitnagil/navigation/home/HomeNavHost.kt +++ b/app/src/main/java/com/threegap/bitnagil/navigation/home/HomeNavHost.kt @@ -3,7 +3,6 @@ package com.threegap.bitnagil.navigation.home import android.annotation.SuppressLint import android.app.Activity import androidx.activity.compose.BackHandler -import androidx.activity.compose.LocalActivity import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.WindowInsets @@ -11,7 +10,6 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.material3.Scaffold import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableLongStateOf import androidx.compose.runtime.mutableStateOf @@ -31,8 +29,8 @@ import com.threegap.bitnagil.designsystem.modifier.clickableWithoutRipple import com.threegap.bitnagil.presentation.screen.home.HomeScreenContainer import com.threegap.bitnagil.presentation.screen.mypage.MyPageScreenContainer import com.threegap.bitnagil.presentation.screen.recommendroutine.RecommendRoutineScreenContainer +import com.threegap.bitnagil.presentation.util.statusbar.NavStatusBarEffect import com.threegap.bitnagil.presentation.util.toast.GlobalBitnagilToast -import com.threegap.bitnagil.util.setStatusBarContentColor @Composable @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @@ -54,11 +52,7 @@ fun HomeNavHost( DoubleBackButtonPressedHandler() - val activity = LocalActivity.current - val isHomeTab = navigator.isHomeRoute - LaunchedEffect(isHomeTab) { - activity?.setStatusBarContentColor(isLightContent = isHomeTab) - } + NavStatusBarEffect(navController = navigator.navController) val selectedBottomTab = navigator.currentHomeRoute ?: navigator.startDestination diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/util/statusbar/NavStatusBarEffect.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/util/statusbar/NavStatusBarEffect.kt new file mode 100644 index 00000000..65f4ff8d --- /dev/null +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/util/statusbar/NavStatusBarEffect.kt @@ -0,0 +1,24 @@ +package com.threegap.bitnagil.presentation.util.statusbar + +import androidx.activity.compose.LocalActivity +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.repeatOnLifecycle +import androidx.navigation.NavController +import androidx.navigation.compose.currentBackStackEntryAsState + +@Composable +fun NavStatusBarEffect(navController: NavController) { + val activity = LocalActivity.current + val navBackStackEntry by navController.currentBackStackEntryAsState() + + LaunchedEffect(navBackStackEntry) { + navBackStackEntry?.repeatOnLifecycle(Lifecycle.State.RESUMED) { + activity?.window?.let { window -> + StatusBarAppearanceManager().applyStatusBarColorByLuminance(window) + } + } + } +} diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/util/statusbar/StatusBarAppearanceManager.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/util/statusbar/StatusBarAppearanceManager.kt new file mode 100644 index 00000000..f8af5bd9 --- /dev/null +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/util/statusbar/StatusBarAppearanceManager.kt @@ -0,0 +1,54 @@ +package com.threegap.bitnagil.presentation.util.statusbar + +import android.graphics.Bitmap +import android.graphics.Color +import android.graphics.Rect +import android.os.Handler +import android.os.Looper +import android.view.PixelCopy +import android.view.Window +import androidx.core.graphics.createBitmap +import androidx.core.view.ViewCompat +import androidx.core.view.WindowInsetsCompat +import androidx.core.graphics.get +import androidx.core.view.WindowInsetsControllerCompat + +class StatusBarAppearanceManager { + fun applyStatusBarColorByLuminance(window: Window) { + val height = getStatusBarHeight(window = window) + if (height <= 0) return + + captureStatusBarBitmap( + window = window, + height = height, + ) { bmp -> + bmp?.let { + val lum = calculateLuminance(it) + WindowInsetsControllerCompat(window, window.decorView).isAppearanceLightStatusBars = (lum > 150) + } + } + } + + private fun getStatusBarHeight(window: Window): Int { + val decorView = window.decorView + val insets = ViewCompat.getRootWindowInsets(decorView) + return insets?.getInsets(WindowInsetsCompat.Type.statusBars())?.top ?: 0 + } + + private fun captureStatusBarBitmap( + window: Window, + height: Int, + onResult: (Bitmap?) -> Unit + ) { + val rect = Rect(0, 0, window.decorView.width, height) + val bmp = createBitmap(rect.width(), rect.height()) + PixelCopy.request(window, rect, bmp, {_ -> onResult(bmp)}, Handler(Looper.getMainLooper())) + } + + private fun calculateLuminance(bitmap: Bitmap): Int { + val x = bitmap.width / 2 + val y = bitmap.height / 2 + val px = bitmap[x, y] + return (0.299 * Color.red(px) + 0.587 * Color.green(px) + 0.114 * Color.blue(px)).toInt() + } +} From b924953a69430b8b299bcea54a83225c82b9a0e7 Mon Sep 17 00:00:00 2001 From: yunsehwan Date: Sun, 26 Apr 2026 20:24:46 +0900 Subject: [PATCH 2/3] =?UTF-8?q?CHORE:=20=EB=AF=B8=EC=82=AC=EC=9A=A9=20?= =?UTF-8?q?=EB=B3=80=EC=88=98=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/threegap/bitnagil/navigation/home/HomeNavigator.kt | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/src/main/java/com/threegap/bitnagil/navigation/home/HomeNavigator.kt b/app/src/main/java/com/threegap/bitnagil/navigation/home/HomeNavigator.kt index a79878b9..a589ae35 100644 --- a/app/src/main/java/com/threegap/bitnagil/navigation/home/HomeNavigator.kt +++ b/app/src/main/java/com/threegap/bitnagil/navigation/home/HomeNavigator.kt @@ -23,9 +23,6 @@ class HomeNavigator( } } - val isHomeRoute: Boolean - @Composable get() = currentHomeRoute == HomeRoute.Home - @Composable fun shouldShowFloatingAction(): Boolean = currentHomeRoute?.showFloatingButton == true From b45a2ccd8a1498639eb01689fd5f92c604ddb8b1 Mon Sep 17 00:00:00 2001 From: yunsehwan Date: Mon, 27 Apr 2026 20:08:37 +0900 Subject: [PATCH 3/3] =?UTF-8?q?FIX:=20StatusBarAppearanceManager=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../util/statusbar/NavStatusBarEffect.kt | 2 +- .../statusbar/StatusBarAppearanceManager.kt | 28 +++++++++++++++++-- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/util/statusbar/NavStatusBarEffect.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/util/statusbar/NavStatusBarEffect.kt index 65f4ff8d..745c1bbb 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/util/statusbar/NavStatusBarEffect.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/util/statusbar/NavStatusBarEffect.kt @@ -17,7 +17,7 @@ fun NavStatusBarEffect(navController: NavController) { LaunchedEffect(navBackStackEntry) { navBackStackEntry?.repeatOnLifecycle(Lifecycle.State.RESUMED) { activity?.window?.let { window -> - StatusBarAppearanceManager().applyStatusBarColorByLuminance(window) + StatusBarAppearanceManager.applyStatusBarColorByLuminance(window) } } } diff --git a/presentation/src/main/java/com/threegap/bitnagil/presentation/util/statusbar/StatusBarAppearanceManager.kt b/presentation/src/main/java/com/threegap/bitnagil/presentation/util/statusbar/StatusBarAppearanceManager.kt index f8af5bd9..dc8500f7 100644 --- a/presentation/src/main/java/com/threegap/bitnagil/presentation/util/statusbar/StatusBarAppearanceManager.kt +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/util/statusbar/StatusBarAppearanceManager.kt @@ -13,7 +13,9 @@ import androidx.core.view.WindowInsetsCompat import androidx.core.graphics.get import androidx.core.view.WindowInsetsControllerCompat -class StatusBarAppearanceManager { +object StatusBarAppearanceManager { + private const val LUMINANCE_THRESHOLD = 150 + fun applyStatusBarColorByLuminance(window: Window) { val height = getStatusBarHeight(window = window) if (height <= 0) return @@ -24,7 +26,8 @@ class StatusBarAppearanceManager { ) { bmp -> bmp?.let { val lum = calculateLuminance(it) - WindowInsetsControllerCompat(window, window.decorView).isAppearanceLightStatusBars = (lum > 150) + WindowInsetsControllerCompat(window, window.decorView).isAppearanceLightStatusBars = (lum > LUMINANCE_THRESHOLD) + it.recycle() } } } @@ -40,9 +43,28 @@ class StatusBarAppearanceManager { height: Int, onResult: (Bitmap?) -> Unit ) { + val width = window.decorView.width + if (width <= 0) { + onResult(null) + return + } + val rect = Rect(0, 0, window.decorView.width, height) val bmp = createBitmap(rect.width(), rect.height()) - PixelCopy.request(window, rect, bmp, {_ -> onResult(bmp)}, Handler(Looper.getMainLooper())) + + try { + PixelCopy.request(window, rect, bmp, { result -> + if (result == PixelCopy.SUCCESS) { + onResult(bmp) + } else { + bmp.recycle() + onResult(null) + } + }, Handler(Looper.getMainLooper())) + } catch (_: Exception) { + bmp.recycle() + onResult(null) + } } private fun calculateLuminance(bitmap: Bitmap): Int {