Android大圆角屏幕适配:InsetsLayout类使用方法及空白屏幕问题求助
Android大圆角屏幕适配:InsetsLayout类使用方法及空白屏幕问题求助
大家好,我现在在做App的Android 16迁移适配,测试大圆角屏幕的虚拟设备时,发现我的视图被屏幕的圆角给“啃”掉了一部分。查了官方文档里的「Apply Rounded Corners」部分,里面提到的InsetsLayout方案正好命中我的需求,于是我照着实现了这个自定义布局类,但官方完全没说具体怎么用这个类。我自己试了一种方式,结果直接出现了空白屏幕,实在搞不定,来求助大家!
我实现的InsetsLayout代码
我按照文档示例实现了这个自定义FrameLayout,还根据@CommonsWare的建议把attrs参数改成了可空类型:
class InsetsLayout(context: Context, attrs: AttributeSet?) : FrameLayout(context, attrs) { override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) { val insets = rootWindowInsets if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && insets != null) { applyRoundedCornerPadding(insets) } super.onLayout(changed, left, top, right, bottom) } @RequiresApi(Build.VERSION_CODES.S) private fun applyRoundedCornerPadding(insets: WindowInsets) { val topLeft = insets.getRoundedCorner(RoundedCorner.POSITION_TOP_LEFT) val topRight = insets.getRoundedCorner(RoundedCorner.POSITION_TOP_RIGHT) val bottomLeft = insets.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_LEFT) val bottomRight = insets.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_RIGHT) val leftRadius = max(topLeft?.radius ?: 0, bottomLeft?.radius ?: 0) val topRadius = max(topLeft?.radius ?: 0, topRight?.radius ?: 0) val rightRadius = max(topRight?.radius ?: 0, bottomRight?.radius ?: 0) val bottomRadius = max(bottomLeft?.radius ?: 0, bottomRight?.radius ?: 0) val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager val windowBounds = windowManager.currentWindowMetrics.bounds val safeArea = Rect( windowBounds.left + leftRadius, windowBounds.top + topRadius, windowBounds.right - rightRadius, windowBounds.bottom - bottomRadius ) val location = intArrayOf(0, 0) getLocationInWindow(location) val leftMargin = location[0] - windowBounds.left val topMargin = location[1] - windowBounds.top val rightMargin = windowBounds.right - right - location[0] val bottomMargin = windowBounds.bottom - bottom - location[1] val layoutBounds = Rect( location[0] + paddingLeft, location[1] + paddingTop, location[0] + width - paddingRight, location[1] + height - paddingBottom ) if (layoutBounds != safeArea && layoutBounds.contains(safeArea)) { setPadding( calculatePadding(leftRadius, leftMargin, paddingLeft), calculatePadding(topRadius, topMargin, paddingTop), calculatePadding(rightRadius, rightMargin, paddingRight), calculatePadding(bottomRadius, bottomMargin, paddingBottom) ) } } private fun calculatePadding(radius1: Int?, radius2: Int?, margin: Int, padding: Int): Int = (max(radius1 ?: 0, radius2 ?: 0) - margin - padding).coerceAtLeast(0) }
我的尝试及遇到的问题
我想着把activity_main的根布局包裹在这个InsetsLayout里,于是在MainActivity的onCreate里写了这段代码:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val parent = InsetsLayout(applicationContext) parent.layoutParams = FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,FrameLayout.LayoutParams.MATCH_PARENT ) setContentView(parent) hideSystemBars() }
结果运行后直接是空白屏幕,完全看不到原来的布局内容。我的activity_main布局是这样的:
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/root" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/fondbleufonce" android:foregroundTintMode="multiply" tools:context=".MainActivity"> <androidx.fragment.app.FragmentContainerView android:id="@+id/nav_host_fragment" android:name="androidx.navigation.fragment.NavHostFragment" android:layout_width="match_parent" android:layout_height="match_parent" app:defaultNavHost="true" app:layout_constraintTop_toTopOf="parent" app:navGraph="@navigation/navigation_graph" tools:layout_editor_absoluteX="18dp" /> </androidx.constraintlayout.widget.ConstraintLayout>
想请教的问题
- 这个InsetsLayout到底应该怎么正确使用,才能让我的布局自动根据屏幕圆角添加padding,避免被裁切?
- 我当前的写法为什么会导致空白屏幕?怎么修复?
麻烦各位大佬帮忙看看,谢谢啦!
内容来源于stack exchange
相关产品推荐
相关产品推荐

