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/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 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..745c1bbb --- /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..dc8500f7 --- /dev/null +++ b/presentation/src/main/java/com/threegap/bitnagil/presentation/util/statusbar/StatusBarAppearanceManager.kt @@ -0,0 +1,76 @@ +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 + +object StatusBarAppearanceManager { + private const val LUMINANCE_THRESHOLD = 150 + + 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 > LUMINANCE_THRESHOLD) + it.recycle() + } + } + } + + 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 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()) + + 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 { + 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() + } +}