如何向我的 UI 添加填充以避免在横向时被显示切口遮挡?

问题描述 投票:0回答:3

display cut-out screenshot

我仍然希望底部导航栏保持相同的长度,但我想在左侧的容器中添加一些填充,以将卡片向右移动一点。我现在的

MainActivity.kt
中有以下代码:

WindowCompat.setDecorFitsSystemWindows(window, false)
    ViewCompat.setOnApplyWindowInsetsListener(binding.root) { view, windowInsets ->
        val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
        view.updateLayoutParams<ViewGroup.MarginLayoutParams> {
            topMargin = insets.top
        }
        binding.bottomNavigationView.updatePadding(bottom = insets.bottom)
        WindowInsetsCompat.CONSUMED
    }

我的

activity_main.xml
ConstraintLayout
组成,其中包含两个元素:
BottomNavigationView
FragmentContainerView

android kotlin landscape-portrait device-orientation
3个回答
2
投票

文档提供了默认的剪切模式选项,而不是填充布局。

LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT - 使用此默认设置, 以纵向模式显示时,内容呈现到剪切区域中, 但在横向模式下显示时,内容会出现黑框

因此,您可以使用以下方式在主题/样式文件中指定:

<item name="android:windowLayoutInDisplayCutoutMode">default</item>

更新

我将其设置为shortEdges,因为我不想要默认行为。横向时,默认行为不会从边缘到边缘。我遇到的问题是卡片被遮挡,所以我想知道如何通过插入边距或填充来解决这个问题。

由于添加填充的位置会根据设备方向发生变化,因此您可以使用

OrientationEventListener

 跟踪方向方向的变化并相应地添加填充。

剪切深度的典型值可以作为屏幕插入的最大值来发现(因为应用程序将以纵向、横向左/右启动);在每种情况下,切口位置都不同。

private var cutoutDepth = 0 WindowCompat.setDecorFitsSystemWindows(window, false) ViewCompat.setOnApplyWindowInsetsListener(binding.root) { view, windowInsets -> val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()) cutoutDepth = Collections.max(listOf(insets.bottom, insets.left, insets.right)) // reset of code is omitted
注意 

cutoutDepth

 变量应该保存在像 ViewModel 这样的永久存储中;你需要处理这个问题。

这里将padding添加到根视图中;但您可以将其级联到片段中的

RecyclerView

private val orientationListener by lazy { object : OrientationEventListener(applicationContext, SensorManager.SENSOR_DELAY_NORMAL) { override fun onOrientationChanged(orientation: Int) { if (orientation == ORIENTATION_UNKNOWN) return val rotation = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) display?.rotation else windowManager.defaultDisplay.rotation when (rotation) { Surface.ROTATION_0 -> { // BOTTOM binding.root.setPadding(0, 0, 0, 0) // reset the padding in portrait Log.d("LOG_TAG", "Orientation: BOTTOM") } Surface.ROTATION_90 -> { // LEFT binding.root.setPadding(cutoutDepth, 0, 0, 0) Log.d("LOG_TAG", "Orientation: LEFT") } Surface.ROTATION_180 -> { // TOP binding.root.setPadding(0, 0, 0, 0) // // reset the padding in upside down (if it's allowed) Log.d("LOG_TAG", "Orientation: TOP") } Surface.ROTATION_270 -> { // RIGHT binding.root.setPadding(0, 0, cutoutDepth, 0) Log.d("LOG_TAG", "Orientation: RIGHT") } } } } } override fun onResume() { super.onResume() // start the orientation listener if (orientationListener.canDetectOrientation()) orientationListener.enable() } override fun onPause() { super.onPause() // stop the orientation listener orientationListener.disable() }
    

2
投票
感谢@Zain 的帮助修复了它!

private var cutoutDepth = 0 override fun onCreate(savedInstanceState: Bundle?) { [...] ViewCompat.setOnApplyWindowInsetsListener(binding.root) { view, windowInsets -> val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()) cutoutDepth = insets.top [...] } [...] } override fun onResume() { super.onResume() // Starts the orientation listener if (orientationListener.canDetectOrientation()) orientationListener.enable() } override fun onPause() { super.onPause() // Stops the orientation listener orientationListener.disable() } private val orientationListener by lazy { object : OrientationEventListener(applicationContext, SensorManager.SENSOR_DELAY_NORMAL) { override fun onOrientationChanged(orientation: Int) { if (orientation == ORIENTATION_UNKNOWN) return when (display?.rotation) { Surface.ROTATION_0 -> { // Bottom - reset the padding in portrait binding.navHostFragmentActivityMain.setPadding(0, 0, 0, 0) } Surface.ROTATION_90 -> { // Left binding.navHostFragmentActivityMain.setPadding(cutoutDepth, 0, 0, 0) } Surface.ROTATION_180 -> { // Top - reset the padding if upside down binding.navHostFragmentActivityMain.setPadding(0, 0, 0, 0) } Surface.ROTATION_270 -> { // Right binding.navHostFragmentActivityMain.setPadding(0, 0, cutoutDepth, 0) } } } } }
最终结果:

end result


0
投票
在Java中,使用这个:

ViewCompat.setOnApplyWindowInsetsListener(binding.getRoot(), (v, insets) -> { Insets systemBarsInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars()); Insets cutoutInsets = insets.getInsets(WindowInsetsCompat.Type.displayCutout()); int leftInset = Math.max(systemBarsInsets.left, cutoutInsets.left); int topInset = Math.max(systemBarsInsets.top, cutoutInsets.top); int rightInset = Math.max(systemBarsInsets.right, cutoutInsets.right); int bottomInset = systemBarsInsets.bottom; v.setPadding(leftInset, topInset, rightInset, bottomInset); return insets; });
如果您的设备有凹口/切口,这将采用切口的最大值并相应地处理填充。

© www.soinside.com 2019 - 2024. All rights reserved.