diff --git a/app/src/main/java/com/nextcloud/client/systembars/SystemBarBackgroundCallbacks.kt b/app/src/main/java/com/nextcloud/client/systembars/SystemBarBackgroundCallbacks.kt new file mode 100644 index 000000000000..a0ebd8ee76ab --- /dev/null +++ b/app/src/main/java/com/nextcloud/client/systembars/SystemBarBackgroundCallbacks.kt @@ -0,0 +1,80 @@ +/* + * Nextcloud - Android Client + * + * SPDX-FileCopyrightText: 2026 Alper Ozturk + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +package com.nextcloud.client.systembars + +import android.app.Activity +import android.app.Application.ActivityLifecycleCallbacks +import android.os.Bundle +import android.widget.FrameLayout +import androidx.annotation.ColorInt +import androidx.core.content.ContextCompat +import com.nextcloud.client.onboarding.FirstRunActivity +import com.nmc.android.ui.LauncherActivity +import com.owncloud.android.R +import com.owncloud.android.authentication.AuthenticatorActivity +import com.owncloud.android.ui.activity.DrawerActivity +import com.owncloud.android.utils.theme.ViewThemeUtils +import dynamiccolor.MaterialDynamicColors +import javax.inject.Provider + +class SystemBarBackgroundCallbacks(private val viewThemeUtilsProvider: Provider) : + ActivityLifecycleCallbacks { + + companion object { + private val dynamicColor = MaterialDynamicColors() + private val excludedActivities = listOf( + LauncherActivity::class, + AuthenticatorActivity::class, + FirstRunActivity::class + ) + + private fun isExcluded(activity: Activity): Boolean = excludedActivities.any { it.isInstance(activity) } + + @JvmStatic + @Suppress("ReturnCount") + fun apply(activity: Activity, viewThemeUtils: ViewThemeUtils) { + if (isExcluded(activity)) return + + val decorView = activity.window?.decorView as? FrameLayout ?: return + val actionBarColor = dynamicColor.surface().getArgb(viewThemeUtils.getScheme(activity)) + val statusBarColor = statusBarColor(activity, actionBarColor) + + val existing = decorView.foreground as? SystemBarsBackgroundDrawable + if (existing != null) { + existing.setColors(statusBarColor, actionBarColor) + return + } + + decorView.foreground = SystemBarsBackgroundDrawable(decorView, statusBarColor, actionBarColor) + } + + @ColorInt + private fun statusBarColor(activity: Activity, @ColorInt actionBarColor: Int): Int { + if (activity is DrawerActivity && activity.isToolbarStyleSearch) { + return ContextCompat.getColor(activity, R.color.bg_default) + } + + return actionBarColor + } + } + + override fun onActivityStarted(activity: Activity) { + apply(activity, viewThemeUtilsProvider.get()) + } + + override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) = Unit + + override fun onActivityResumed(activity: Activity) = Unit + + override fun onActivityPaused(activity: Activity) = Unit + + override fun onActivityStopped(activity: Activity) = Unit + + override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) = Unit + + override fun onActivityDestroyed(activity: Activity) = Unit +} diff --git a/app/src/main/java/com/nextcloud/client/systembars/SystemBarsBackgroundDrawable.kt b/app/src/main/java/com/nextcloud/client/systembars/SystemBarsBackgroundDrawable.kt new file mode 100644 index 000000000000..1d4bf77a206c --- /dev/null +++ b/app/src/main/java/com/nextcloud/client/systembars/SystemBarsBackgroundDrawable.kt @@ -0,0 +1,80 @@ +/* + * Nextcloud - Android Client + * + * SPDX-FileCopyrightText: 2026 Alper Ozturk + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +package com.nextcloud.client.systembars + +import android.graphics.Canvas +import android.graphics.ColorFilter +import android.graphics.Paint +import android.graphics.PixelFormat +import android.graphics.drawable.Drawable +import android.view.View +import androidx.annotation.ColorInt +import androidx.core.graphics.Insets +import androidx.core.view.ViewCompat +import androidx.core.view.WindowInsetsCompat + +class SystemBarsBackgroundDrawable( + private val decorView: View, + @ColorInt statusBarColor: Int, + @ColorInt navigationBarColor: Int +) : Drawable() { + + private val statusBarPaint = Paint().apply { color = statusBarColor } + private val navigationBarPaint = Paint().apply { color = navigationBarColor } + + fun setColors(@ColorInt statusBarColor: Int, @ColorInt navigationBarColor: Int) { + if (statusBarPaint.color == statusBarColor && navigationBarPaint.color == navigationBarColor) { + return + } + statusBarPaint.color = statusBarColor + navigationBarPaint.color = navigationBarColor + invalidateSelf() + } + + override fun draw(canvas: Canvas) { + val insets = ViewCompat.getRootWindowInsets(decorView) ?: return + drawStatusBar(canvas, insets.getInsets(WindowInsetsCompat.Type.statusBars())) + drawNavigationBar(canvas, insets.getInsets(WindowInsetsCompat.Type.navigationBars())) + } + + private fun drawStatusBar(canvas: Canvas, insets: Insets) { + if (insets.top == 0) { + return + } + canvas.drawRect(left, top, right, top + insets.top, statusBarPaint) + } + + private fun drawNavigationBar(canvas: Canvas, insets: Insets) { + if (insets.bottom > 0) { + canvas.drawRect(left, bottom - insets.bottom, right, bottom, navigationBarPaint) + } + if (insets.left > 0) { + canvas.drawRect(left, top, left + insets.left, bottom, navigationBarPaint) + } + if (insets.right > 0) { + canvas.drawRect(right - insets.right, top, right, bottom, navigationBarPaint) + } + } + + private val left: Float get() = bounds.left.toFloat() + private val top: Float get() = bounds.top.toFloat() + private val right: Float get() = bounds.right.toFloat() + private val bottom: Float get() = bounds.bottom.toFloat() + + override fun setAlpha(alpha: Int) { + statusBarPaint.alpha = alpha + navigationBarPaint.alpha = alpha + } + + override fun setColorFilter(colorFilter: ColorFilter?) { + statusBarPaint.colorFilter = colorFilter + navigationBarPaint.colorFilter = colorFilter + } + + @Deprecated("Deprecated in Java") + override fun getOpacity(): Int = PixelFormat.TRANSLUCENT +} diff --git a/app/src/main/java/com/owncloud/android/MainApp.java b/app/src/main/java/com/owncloud/android/MainApp.java index 2afd5ade94ef..17b5b333721f 100644 --- a/app/src/main/java/com/owncloud/android/MainApp.java +++ b/app/src/main/java/com/owncloud/android/MainApp.java @@ -58,6 +58,7 @@ import com.nextcloud.client.preferences.AppPreferences; import com.nextcloud.client.preferences.AppPreferencesImpl; import com.nextcloud.client.preferences.DarkMode; +import com.nextcloud.client.systembars.SystemBarBackgroundCallbacks; import com.nextcloud.ui.composeActivity.ComposeProcessTextAlias; import com.nextcloud.utils.extensions.ContextExtensionsKt; import com.nextcloud.utils.mdm.MDMConfig; @@ -292,6 +293,7 @@ public void onCreate() { insertConscrypt(); registerActivityLifecycleCallbacks(new ActivityInjector()); + registerActivityLifecycleCallbacks(new SystemBarBackgroundCallbacks(viewThemeUtilsProvider)); //update the app restart count when app is launched by the user inAppReviewHelper.resetAndIncrementAppRestartCounter(); diff --git a/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java b/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java index 1b3d1a06e8aa..e1680466f450 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java +++ b/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java @@ -59,6 +59,7 @@ import com.nextcloud.client.onboarding.FirstRunActivity; import com.nextcloud.client.player.media3.PlaybackModel; import com.nextcloud.client.preferences.AppPreferences; +import com.nextcloud.client.systembars.SystemBarBackgroundCallbacks; import com.nextcloud.client.utils.IntentUtil; import com.nextcloud.common.NextcloudClient; import com.nextcloud.ui.ChooseAccountDialogFragment; @@ -316,6 +317,7 @@ public void highlightNavigationViewItem(int menuItemId) { NavigationViewExtensionsKt.highlightNavigationView(drawerNavigationView, bottomNavigationView, menuItemId); + SystemBarBackgroundCallbacks.apply(this, viewThemeUtils); Log_OC.d(TAG, "New menu item is: " + menuItemId); }