Skip to content

Commit

Permalink
Insets on iOS (#577)
Browse files Browse the repository at this point in the history
API is the same as for Android
WindowInsets.Companion.concreteInsetsName
  • Loading branch information
dima-avdeev-jb committed May 26, 2023
1 parent 47f4c4b commit 4ddcf93
Show file tree
Hide file tree
Showing 14 changed files with 858 additions and 66 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
/*
* Copyright 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package androidx.compose.foundation.layout

import androidx.compose.runtime.Composable
import androidx.compose.runtime.InternalComposeApi
import androidx.compose.ui.uikit.*
import androidx.compose.ui.unit.dp

private val ZeroInsets = WindowInsets(0, 0, 0, 0)

/**
* This insets represents iOS SafeAreas.
*/
private val WindowInsets.Companion.iosSafeArea: WindowInsets
@Composable
@OptIn(InternalComposeApi::class)
get() = WindowInsets(
top = LocalSafeAreaState.current.value.top,
bottom = LocalSafeAreaState.current.value.bottom,
left = LocalSafeAreaState.current.value.left,
right = LocalSafeAreaState.current.value.right,
)

/**
* This insets represents iOS layoutMargins.
*/
private val WindowInsets.Companion.layoutMargins: WindowInsets
@Composable
@OptIn(InternalComposeApi::class)
get() = WindowInsets(
top = LocalLayoutMarginsState.current.value.top,
bottom = LocalLayoutMarginsState.current.value.bottom,
left = LocalLayoutMarginsState.current.value.left,
right = LocalLayoutMarginsState.current.value.right,
)

/**
* An insets type representing the window of a caption bar.
* It is useless for iOS.
*/
val WindowInsets.Companion.captionBar get() = ZeroInsets

/**
* This [WindowInsets] represents the area with the display cutout (e.g. for camera).
*/
val WindowInsets.Companion.displayCutout: WindowInsets
@Composable
@OptIn(InternalComposeApi::class)
get() = when (LocalInterfaceOrientationState.current.value) {
InterfaceOrientation.Portrait -> iosSafeArea.only(WindowInsetsSides.Top)
InterfaceOrientation.PortraitUpsideDown -> iosSafeArea.only(WindowInsetsSides.Bottom)
InterfaceOrientation.LandscapeLeft -> iosSafeArea.only(WindowInsetsSides.Right)
InterfaceOrientation.LandscapeRight -> iosSafeArea.only(WindowInsetsSides.Left)
}

/**
* An insets type representing the window of an "input method",
* for iOS IME representing the software keyboard.
*
* TODO: Animation doesn't work on iOS yet
*/
val WindowInsets.Companion.ime: WindowInsets
@Composable
@OptIn(InternalComposeApi::class)
get() = WindowInsets(bottom = LocalKeyboardOverlapHeightState.current.value.dp)

/**
* These insets represents the space where system gestures have priority over application gestures.
*/
val WindowInsets.Companion.mandatorySystemGestures: WindowInsets
@Composable
get() = iosSafeArea.only(WindowInsetsSides.Top + WindowInsetsSides.Bottom)

/**
* These insets represent where system UI places navigation bars.
* Interactive UI should avoid the navigation bars area.
*/
val WindowInsets.Companion.navigationBars: WindowInsets
@Composable
get() = iosSafeArea.only(WindowInsetsSides.Bottom)

/**
* These insets represents status bar.
*/
val WindowInsets.Companion.statusBars: WindowInsets
@Composable
@OptIn(InternalComposeApi::class)
get() = when (LocalInterfaceOrientationState.current.value) {
InterfaceOrientation.Portrait -> iosSafeArea.only(WindowInsetsSides.Top)
else -> ZeroInsets
}

/**
* These insets represents all system bars.
* Includes [statusBars], [captionBar] as well as [navigationBars], but not [ime].
*/
val WindowInsets.Companion.systemBars: WindowInsets
@Composable
get() = iosSafeArea

/**
* The systemGestures insets represent the area of a window where system gestures have
* priority and may consume some or all touch input, e.g. due to the system bar
* occupying it, or it being reserved for touch-only gestures.
*/
val WindowInsets.Companion.systemGestures: WindowInsets
@Composable
get() = layoutMargins // the same as iosSafeArea.add(WindowInsets(left = 16.dp, right = 16.dp))

/**
* Returns the tappable element insets.
*/
val WindowInsets.Companion.tappableElement: WindowInsets
@Composable
get() = iosSafeArea.only(WindowInsetsSides.Top)

/**
* The insets for the curved areas in a waterfall display.
* It is useless for iOS.
*/
val WindowInsets.Companion.waterfall: WindowInsets get() = ZeroInsets

/**
* The insets that include areas where content may be covered by other drawn content.
* This includes all [systemBars], [displayCutout], and [ime].
*/
val WindowInsets.Companion.safeDrawing
@Composable
get() = systemBars.union(ime).union(displayCutout)

/**
* The insets that include areas where gestures may be confused with other input,
* including [systemGestures], [mandatorySystemGestures], [waterfall], and [tappableElement].
*/
val WindowInsets.Companion.safeGestures: WindowInsets
@Composable
get() = tappableElement.union(mandatorySystemGestures).union(systemGestures).union(waterfall)

/**
* The insets that include all areas that may be drawn over or have gesture confusion,
* including everything in [safeDrawing] and [safeGestures].
*/
val WindowInsets.Companion.safeContent: WindowInsets
@Composable
get() = safeDrawing.union(safeGestures)

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2022 The Android Open Source Project
* Copyright 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -21,8 +21,5 @@ import androidx.compose.ui.unit.dp
import androidx.compose.runtime.Composable

@Composable
internal actual fun WindowInsets.Companion.systemBarsForVisualComponents(): WindowInsets {
return WindowInsets(0.dp, 0.dp, 0.dp, 0.dp)
}
// @Composable
// get() = WindowInsets(0.dp, 0.dp, 0.dp, 0.dp)
internal actual fun WindowInsets.Companion.systemBarsForVisualComponents(): WindowInsets =
WindowInsets(0.dp, 0.dp, 0.dp, 0.dp)
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package androidx.compose.material3

import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.ui.unit.dp
import androidx.compose.runtime.Composable

@Composable
internal actual fun WindowInsets.Companion.systemBarsForVisualComponents(): WindowInsets =
WindowInsets(0.dp, 0.dp, 0.dp, 0.dp)
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package androidx.compose.material3

import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.ui.unit.dp
import androidx.compose.runtime.Composable

@Composable
internal actual fun WindowInsets.Companion.systemBarsForVisualComponents(): WindowInsets =
WindowInsets(0.dp, 0.dp, 0.dp, 0.dp)
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package androidx.compose.material3

import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.systemBars
import androidx.compose.runtime.Composable

@Composable
internal actual fun WindowInsets.Companion.systemBarsForVisualComponents(): WindowInsets =
WindowInsets.systemBars
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import shared

struct ContentView: View {
var body: some View {
ComposeView()
ComposeView().ignoresSafeArea(.all)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,10 @@

package androidx.compose.mpp.demo

import androidx.compose.runtime.remember
import androidx.compose.ui.window.ComposeUIViewController

// TODO This module is just a proxy to run the demo from mpp:demo. Figure out how to get rid of it.
// If it is removed, there is no available configuration in IDE
fun getViewControllerWithCompose() = ComposeUIViewController {
val app = remember() { App() }
app.Content()
IosDemo()
}
1 change: 1 addition & 0 deletions compose/mpp/demo/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ kotlin {
dependencies {
implementation(project(":compose:foundation:foundation"))
implementation(project(":compose:foundation:foundation-layout"))
implementation(project(":compose:material3:material3"))
implementation(project(":compose:material:material"))
implementation(project(":compose:mpp"))
implementation(project(":compose:runtime:runtime"))
Expand Down

0 comments on commit 4ddcf93

Please sign in to comment.