我仍然希望底部导航栏保持相同的长度,但我想在左侧的容器中添加一些填充,以将卡片向右移动一点。我现在的
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
。
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()
}
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)
}
}
}
}
}
最终结果:
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;
});
如果您的设备有凹口/切口,这将采用切口的最大值并相应地处理填充。