Hassen
Hassen

Reputation: 31

statusBar compose multiplatform color

enter image description here

I want to change the statusBar opacity am working on CommonMain

Upvotes: 1

Views: 708

Answers (2)

This solution is based on the links provided below

1)Kotlin

2) Jetpack Compose Side Effect to update Android or iOS status-bar and navigation-bar color

3) iPhone Pro version with dynamic island status bar height issue #4248]


To Change the StatusBar color, declare an expect fun as follows:

  1. In Common Main
    @Composable
    expect fun PlatformColors(statusBarColor: Color, navBarColor: Color)
  1. In iOSMain
import androidx.compose.ui.graphics.Color
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.remember
import kotlinx.cinterop.ExperimentalForeignApi
import kotlinx.cinterop.*
import kotlinx.cinterop.zeroValue
import platform.CoreGraphics.*
import platform.CoreGraphics.CGRectMake
import platform.CoreGraphics.CGContextRef
import platform.UIKit.UIApplication
import platform.UIKit.UIColor
import platform.UIKit.UINavigationBar
import platform.UIKit.UIView
import platform.UIKit.UIWindow
import platform.UIKit.statusBarManager
import platform.UIKit.*
    @OptIn(ExperimentalForeignApi::class)
    @Composable
    private fun statusBarView() = remember {
    val keyWindow: UIWindow? =
        UIApplication.sharedApplication.windows.firstOrNull { (it as? UIWindow)?.isKeyWindow() == true } as? UIWindow
    val safeAreaInsets = UIApplication.sharedApplication.keyWindow?.safeAreaInsets
    val width = UIScreen.mainScreen.bounds.useContents { this.size.width }
    var topInsets = 0.0

    safeAreaInsets?.let {
        topInsets = safeAreaInsets.useContents {
            this.top
        }
    }
    val tag = 3848245L // https://stackoverflow.com/questions/56651245/how-to-change-the-status-bar-background-color-and-text-color-on-ios-13

    val statusBarView = UIView(frame = CGRectMake(0.0,0.0, width, topInsets))

    keyWindow?.viewWithTag(tag) ?: run {
        statusBarView.tag = tag
        statusBarView.layer.zPosition = 999999.0
        keyWindow?.addSubview(statusBarView)
        statusBarView
    }
}
    
    
    @Composable
    actual fun PlatformColors(
        statusBarColor: Color,
        navBarColor: Color
    ) {
        val statusBar = statusBarView()
        SideEffect {
            statusBar?.backgroundColor = statusBarColor.toUIColor()
            UINavigationBar.appearance().backgroundColor = navBarColor.toUIColor()
        }
    }
    
    private fun Color.toUIColor(): UIColor = UIColor(
        red = this.red.toDouble(),
        green = this.green.toDouble(),
        blue = this.blue.toDouble(),
        alpha = this.alpha.toDouble()
    )
  1. androidMain
    import androidx.activity.ComponentActivity
    import androidx.compose.runtime.Composable
    import androidx.compose.runtime.SideEffect
    import androidx.compose.runtime.remember
    import androidx.compose.ui.graphics.Color
    import androidx.compose.ui.input.key.Key.Companion.Window
    import androidx.compose.ui.platform.LocalContext
    import androidx.media3.common.Timeline
    
    @Composable
    actual fun PlatformColors(statusBarColor: Color, navBarColor: Color){
        val activity = LocalContext.current as ComponentActivity
        val window = activity.window
    
        window.statusBarColor = statusBarColor.value.toInt()
    }

Now that the code part is done, we can use different colors for different screens by calling this method:

    PlatformColors(Color.gray, Color.red)

Call this method from the screen where you want to change the status and navigation bar colors. That's it! The colors will change on the screen where you invoke this function.

Upvotes: 0

Hassen
Hassen

Reputation: 31

I discovered that you have to write code natively edge-to-edge by using enableEdgeToEdge() in your activity, then handle necessary paddings in your screens using .systemBarsPadding() in your modifier and in iOS also you need ignoreSafeArea.

Upvotes: 0

Related Questions