Skip to content

Commit

Permalink
Fix safe area issues
Browse files Browse the repository at this point in the history
  • Loading branch information
levinli303 committed Sep 14, 2024
1 parent 3f05a05 commit d05cde6
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 48 deletions.
2 changes: 1 addition & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:installLocation="auto"
android:versionCode="560"
android:versionCode="561"
android:versionName="1.7.7">

<uses-feature android:name="android.hardware.type.pc" android:required="false" />
Expand Down
17 changes: 10 additions & 7 deletions app/src/main/java/space/celestia/mobilecelestia/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -274,16 +274,16 @@ class MainActivity : AppCompatActivity(R.layout.activity_main),
}

val isRTL = resources.configuration.layoutDirection == LayoutDirection.RTL
ViewCompat.setOnApplyWindowInsetsListener(drawerLayout) { _, insets ->
// TODO: the suggested replacement for the deprecated methods does not work
val builder = WindowInsetsCompat.Builder(insets).setSystemWindowInsets(Insets.of(if (isRTL) insets.systemWindowInsetLeft else 0 , insets.systemWindowInsetTop, if (isRTL) 0 else insets.systemWindowInsetRight, insets.systemWindowInsetBottom))
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.drawer)) { _, insets ->
val systemBarInsets = insets.getInsetsIgnoringVisibility(WindowInsetsCompat.Type.systemBars())
val builder = WindowInsetsCompat.Builder(insets).setInsets(WindowInsetsCompat.Type.systemBars(), Insets.of(if (isRTL) systemBarInsets.left else 0 , systemBarInsets.top, if (isRTL) 0 else systemBarInsets.right, systemBarInsets.bottom))
return@setOnApplyWindowInsetsListener builder.build()
}

val bottomSheetContainer = findViewById<FrameLayout>(R.id.bottom_sheet)
ViewCompat.setOnApplyWindowInsetsListener(bottomSheetContainer) { _, insets ->
// TODO: the suggested replacement for the deprecated methods does not work
val builder = WindowInsetsCompat.Builder(insets).setSystemWindowInsets(Insets.of(0, 0, 0, insets.systemWindowInsetBottom))
val systemBarInsets = insets.getInsetsIgnoringVisibility(WindowInsetsCompat.Type.systemBars())
val builder = WindowInsetsCompat.Builder(insets).setInsets(WindowInsetsCompat.Type.systemBars(), Insets.of(0, 0, 0, systemBarInsets.bottom))
return@setOnApplyWindowInsetsListener builder.build()
}
findViewById<FrameLayout>(R.id.drawer).systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
Expand Down Expand Up @@ -369,10 +369,12 @@ class MainActivity : AppCompatActivity(R.layout.activity_main),
private fun updateConfiguration(configuration: Configuration, windowInsets: WindowInsetsCompat?) {
val isRTL = configuration.layoutDirection == LayoutDirection.RTL

val hasRegularHorizontalSpace = configuration.screenWidthDp > SheetLayout.sheetMaxFullWidthDp

val safeInsets = EdgeInsets(
EdgeInsets(windowInsets),
windowInsets,
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) RoundedCorners(windowInsets) else RoundedCorners(0, 0, 0, 0),
configuration
hasRegularHorizontalSpace
)

val safeInsetStart = if (isRTL) safeInsets.right else safeInsets.left
Expand All @@ -391,6 +393,7 @@ class MainActivity : AppCompatActivity(R.layout.activity_main),

val bottomSheetContainer = findViewById<SheetLayout>(R.id.bottom_sheet_overlay)
bottomSheetContainer.edgeInsets = safeInsets
bottomSheetContainer.useLandscapeLayout = hasRegularHorizontalSpace
bottomSheetContainer.requestLayout()

(supportFragmentManager.findFragmentById(R.id.celestia_fragment_container) as? CelestiaFragment)?.handleInsetsChanged(safeInsets)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,14 +120,6 @@ class BrowserFragment : Fragment(), BrowserRootFragment, NavigationBarView.OnIte
loadingIndicator = view.findViewById(R.id.loading_indicator)
browserContainer = view.findViewById(R.id.browser_container)
navigation = view.findViewById(R.id.navigation)

ViewCompat.setOnApplyWindowInsetsListener(view.findViewById(R.id.navigation_container)) { _, insets ->
// Consume bottom insets because we have a bottom bar now
// TODO: the suggested replacement for the deprecated methods does not work
val builder = WindowInsetsCompat.Builder(insets).setSystemWindowInsets(Insets.of(insets.systemWindowInsetLeft , insets.systemWindowInsetTop, insets.systemWindowInsetRight, 0))
return@setOnApplyWindowInsetsListener builder.build()
}

return view
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,44 @@

package space.celestia.mobilecelestia.common

import android.content.res.Configuration
import androidx.core.graphics.Insets
import androidx.core.view.DisplayCutoutCompat
import androidx.core.view.WindowInsetsCompat
import kotlin.math.max

class EdgeInsets(val left: Int = 0, val top: Int = 0, val right: Int = 0, val bottom: Int = 0) {
constructor(insets: WindowInsetsCompat?) : this(insets?.displayCutout)
class EdgeInsets {
val left: Int
val top: Int
val right: Int
val bottom: Int

constructor(left: Int = 0, top: Int = 0, right: Int = 0, bottom: Int = 0) {
this.left = left
this.top = top
this.right = right
this.bottom = bottom
}

constructor(cutout: DisplayCutoutCompat?) : this(
cutout?.safeInsetLeft ?: 0,
cutout?.safeInsetTop ?: 0,
cutout?.safeInsetRight ?: 0,
cutout?.safeInsetBottom ?: 0)

constructor(edgeInsets: EdgeInsets, roundedCorners: RoundedCorners, configuration: Configuration) : this(
if (configuration.orientation == Configuration.ORIENTATION_PORTRAIT) edgeInsets.left else max(edgeInsets.left, max(roundedCorners.topLeft, roundedCorners.bottomLeft)),
if (configuration.orientation != Configuration.ORIENTATION_PORTRAIT) edgeInsets.top else max(edgeInsets.top, max(roundedCorners.topLeft, roundedCorners.topRight)),
if (configuration.orientation == Configuration.ORIENTATION_PORTRAIT) edgeInsets.right else max(edgeInsets.right, max(roundedCorners.topRight, roundedCorners.bottomRight)),
if (configuration.orientation != Configuration.ORIENTATION_PORTRAIT) edgeInsets.bottom else max(edgeInsets.bottom, max(roundedCorners.bottomLeft, roundedCorners.bottomRight))
)
constructor(insets: Insets?) : this(
insets?.left ?: 0,
insets?.top ?: 0,
insets?.right ?: 0,
insets?.bottom ?: 0)

constructor(insets: WindowInsetsCompat?, roundedCorners: RoundedCorners, hasRegularHorizontalSpace: Boolean) {
val displayCutout = EdgeInsets(insets?.displayCutout)
val systemBarInsets = EdgeInsets(insets?.getInsets(WindowInsetsCompat.Type.systemBars()))
val edgeInsets = EdgeInsets(max(displayCutout.left, systemBarInsets.left), max(displayCutout.top, systemBarInsets.top), max(displayCutout.right, systemBarInsets.right), max(displayCutout.bottom, systemBarInsets.bottom))

left = if (!hasRegularHorizontalSpace) edgeInsets.left else max(edgeInsets.left, max(roundedCorners.topLeft, roundedCorners.bottomLeft))
top = if (hasRegularHorizontalSpace) edgeInsets.top else max(edgeInsets.top, max(roundedCorners.topLeft, roundedCorners.topRight))
right = if (!hasRegularHorizontalSpace) edgeInsets.right else max(edgeInsets.right, max(roundedCorners.topRight, roundedCorners.bottomRight))
bottom = if (hasRegularHorizontalSpace) edgeInsets.bottom else max(edgeInsets.bottom, max(roundedCorners.bottomLeft, roundedCorners.bottomRight))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import androidx.customview.widget.ViewDragHelper
import kotlin.math.ceil
import kotlin.math.max
import kotlin.math.min

Expand All @@ -29,6 +28,7 @@ class SheetLayout(context: Context, attrs: AttributeSet): ViewGroup(context, att
private var capturedViewY: Int? = null

var edgeInsets: EdgeInsets = EdgeInsets()
var useLandscapeLayout = false

init {
val callback = object: ViewDragHelper.Callback() {
Expand All @@ -52,7 +52,8 @@ class SheetLayout(context: Context, attrs: AttributeSet): ViewGroup(context, att
}

override fun clampViewPositionVertical(child: View, top: Int, dy: Int): Int {
return min(max(top, max(height - ceil(sheetMaxHeightRatio * height).toInt(), edgeInsets.top)), (height - sheetHandleHeight * resources.displayMetrics.density - edgeInsets.bottom).toInt())
val maxHeight = ((height - edgeInsets.top - edgeInsets.bottom) * sheetMaxHeightRatio).toInt()
return min(max(top, max(height - maxHeight - edgeInsets.bottom, edgeInsets.top)), (height - sheetHandleHeight * resources.displayMetrics.density - edgeInsets.bottom).toInt())
}
}
dragHelper = ViewDragHelper.create(this, callback)
Expand Down Expand Up @@ -90,7 +91,7 @@ class SheetLayout(context: Context, attrs: AttributeSet): ViewGroup(context, att
val containerWidth = resolveSizeAndState(0, widthMeasureSpec, 0)
val containerHeight = resolveSizeAndState(0, heightMeasureSpec, 0)
val density = resources.displayMetrics.density
val shouldNotOccupyFullWidth = (containerWidth / density) > sheetMaxFullWidthDp
val shouldNotOccupyFullWidth = useLandscapeLayout

for (i in 0 until childCount) {
val child = getChildAt(i)
Expand All @@ -99,7 +100,7 @@ class SheetLayout(context: Context, attrs: AttributeSet): ViewGroup(context, att
continue

val childWidth = if (shouldNotOccupyFullWidth) calculateChildWidth(containerWidth, density) else (containerWidth - edgeInsets.left - edgeInsets.right)
val childHeight = min(containerHeight - edgeInsets.top, ceil(containerHeight * sheetMaxHeightRatio).toInt())
val childHeight = min(containerHeight - edgeInsets.top, edgeInsets.bottom + ((containerHeight - edgeInsets.top - edgeInsets.bottom) * sheetMaxHeightRatio).toInt())
child.measure(MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.EXACTLY))
}
setMeasuredDimension(containerWidth, containerHeight)
Expand All @@ -112,14 +113,14 @@ class SheetLayout(context: Context, attrs: AttributeSet): ViewGroup(context, att
val containerWidth = right - left
val containerHeight = bottom - top

val shouldNotOccupyFullWidth = (containerWidth / density) > sheetMaxFullWidthDp
val shouldNotOccupyFullWidth = useLandscapeLayout

for (i in 0 until childCount) {
val child = getChildAt(i)
if (child.visibility == GONE)
continue

val sheetHeight = min(containerHeight - edgeInsets.top, ceil(containerHeight * sheetMaxHeightRatio).toInt())
val sheetHeight = min(containerHeight - edgeInsets.top, edgeInsets.bottom + ((containerHeight - edgeInsets.top - edgeInsets.bottom) * sheetMaxHeightRatio).toInt())

var y = containerHeight - sheetHeight
if (child == capturedView) {
Expand Down Expand Up @@ -149,14 +150,13 @@ class SheetLayout(context: Context, attrs: AttributeSet): ViewGroup(context, att
return max(widthLowerBound, min(widthUpperBound, sheetStandardWidthDp * density)).toInt()
}

private companion object {
const val TAG = "SheetLayout"
const val sheetPaddingNonFullWidthDp = 16
const val sheetStandardWidthDp = 320
const val sheetMinWidthRatio = 0.3f
const val sheetMaxWidthRatio = 0.5f
const val sheetMaxHeightRatio = 0.9
const val sheetHandleHeight = 30
companion object {
private const val sheetPaddingNonFullWidthDp = 16
private const val sheetStandardWidthDp = 320
private const val sheetMinWidthRatio = 0.3f
private const val sheetMaxWidthRatio = 0.5f
private const val sheetMaxHeightRatio = 0.9
private const val sheetHandleHeight = 30
const val sheetMaxFullWidthDp = 600
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,12 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.selection.SelectionContainer
Expand All @@ -34,6 +38,7 @@ import androidx.compose.ui.platform.ViewCompositionStrategy
import androidx.compose.ui.platform.rememberNestedScrollInteropConnection
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.unit.dp
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
Expand Down Expand Up @@ -88,22 +93,28 @@ class DestinationDetailFragment : NavigationFragment.SubFragment() {
val scroll = rememberScrollState(0)
val nestedScrollInterop = rememberNestedScrollInteropConnection()
Column(modifier = Modifier
.fillMaxSize()
.nestedScroll(nestedScrollInterop)
.padding(
start = dimensionResource(id = R.dimen.common_page_medium_margin_horizontal),
end = dimensionResource(id = R.dimen.common_page_medium_margin_horizontal),
),
verticalArrangement = Arrangement.SpaceBetween
) {
SelectionContainer(modifier = Modifier
.verticalScroll(scroll)
.weight(1.0f)
.fillMaxWidth()
.padding(
top = dimensionResource(id = R.dimen.common_page_medium_margin_vertical),
)
) {
Text(text = item?.description ?: "", color = colorResource(id = com.google.android.material.R.color.material_on_background_emphasis_medium), style = MaterialTheme.typography.bodyLarge)
Box(modifier = Modifier.weight(1.0f).fillMaxWidth()) {
SelectionContainer(
modifier = Modifier
.verticalScroll(scroll)
.padding(
top = dimensionResource(id = R.dimen.common_page_medium_margin_vertical),
)
) {
Text(
text = item?.description ?: "",
color = colorResource(id = com.google.android.material.R.color.material_on_background_emphasis_medium),
style = MaterialTheme.typography.bodyLarge
)
}
}
FilledTonalButton(modifier = Modifier
.fillMaxWidth()
Expand Down

0 comments on commit d05cde6

Please sign in to comment.