效果示意图:
Ok,可以先创建一个kt文件,把这些扩展方法放进去。
核心思路就是注册Window
的Insert
设置监听。
data class ViewPaddingData(
val left: Int,
val top: Int,
val right: Int,
val bottom: Int
)
/**
* 可以对 [Activity] 的 [Window] 添加 [WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS],这个flag可以
* activity的布局不受限制
*
* @receiver Window
*/
fun Window.addNoLimitFalgs() {
addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)
decorView.systemUiVisibility = decorView.systemUiVisibility or
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
}
@RequiresApi(Build.VERSION_CODES.R)
@SuppressLint("WrongConstant")
fun View.setViewInsertAfterWindowInsertApplyed(
left: Boolean = false,
right: Boolean = false,
top: Boolean = false,
bottom: Boolean = false,
) {
// Android 11 以上可以使用WindowInsets.Type.statusBars()这个api
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
// window的insert设置好后会执行下面的lambda表达式
doOnApplyWindowInsets { _, windowInsetsCompat, _ ->
val insets = windowInsetsCompat.systemWindowInsets
// 获取状态栏高度
val statusBarHeight = windowInsetsCompat.getInsert(WindowInsets.Type.statusBars()).top
updatePadding(
if (left) insets.left else paddingLeft,
if (top) max(insets.top, statusBarHeight) else paddingTop,
if (right) insets.right else paddingRight,
if (bottom) insets.bottom else paddingBottom
)
}
}
}
@SuppressLint("RestrictedApi")
fun View.doOnApplyWindowInsets(
doSomeThingAfterApplyWindowInsert: (View, WindowInsetsCompat, ViewPaddingData) -> Unit
) {
val paddingState = getViewPaddingData(this)
// 核心是注册这个回调
ViewCompat.setOnApplyWindowInsetsListener(this) { v, insets ->
doSomeThingAfterApplyWindowInsert(v, insets, paddingState)
insets
}
requestApplyInsetsWhenAttached(this)
}
private fun getViewPaddingData(view: View) =
ViewPaddingData(
view.paddingLeft,
view.paddingTop,
view.paddingRight,
view.paddingBottom,
)
使用方式Activity
中:
ovrride fun onCreate() {
// 1 给window添加flags
window.addNoLimitFalgs()
// 执行完 1 后,能看到布局已经充满屏幕,这个时候可以open抽屉观察,抽屉是符合效果的,接下来就是设置一个顶部的padding
// 2. 比如布局中的第一个子view,比如说一般顶部是一个AppBarLayout,那么就可以
appBarLayout.setViewInsertAfterWindowInsertApplyed(true, true, true, false)
}