Skip to content

Commit

Permalink
feat: 简化兼容实现,修正消费逻辑
Browse files Browse the repository at this point in the history
  • Loading branch information
xiaocydx committed Dec 30, 2023
1 parent 6c2746a commit cea8630
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ package com.xiaocydx.insets.compat
import android.annotation.SuppressLint
import android.graphics.Rect
import android.os.Build
import android.util.SparseArray
import android.view.View
import android.view.WindowInsets
import androidx.annotation.ChecksSdkIntAtLeast
Expand Down Expand Up @@ -147,7 +146,6 @@ private class WindowInsetsImmutableListener(
@RequiresApi(21)
@SuppressLint("PrivateApi")
private object InsetsCompatReflection : Reflection {
private var mKeyedTagsField: FieldCache? = null
private var mListenerInfoField: FieldCache? = null
private var mOnApplyWindowInsetsListenerField: FieldCache? = null
private var mStableInsetsField: FieldCache? = null
Expand All @@ -163,7 +161,6 @@ private object InsetsCompatReflection : Reflection {
val proxyListenerClass = Class.forName("androidx.core.view." +
"WindowInsetsAnimationCompat\$Impl21\$Impl21OnApplyWindowInsetsListener")
val viewFields = viewClass.declaredInstanceFields
mKeyedTagsField = viewFields.find("mKeyedTags").toCache()
mListenerInfoField = viewFields.find("mListenerInfo").toCache()
mOnApplyWindowInsetsListenerField = listenerInfoClass
.declaredInstanceFields.find("mOnApplyWindowInsetsListener").toCache()
Expand All @@ -174,7 +171,6 @@ private object InsetsCompatReflection : Reflection {
InsetsCompatReflection.proxyListenerClass = proxyListenerClass
reflectSucceed = true
}.onFailure {
mKeyedTagsField = null
mListenerInfoField = null
mOnApplyWindowInsetsListenerField = null
mStableInsetsField = null
Expand Down Expand Up @@ -203,11 +199,6 @@ private object InsetsCompatReflection : Reflection {
}

/**
* compileOnly依赖AndroidX core,访问`androidx.core.R.id.tag_window_insets_animation_callback`,
* 源码会爆红,但编译能通过,改为implementation依赖AndroidX core,虽然能解决爆红问题,但是不符合初衷,
* 在values目录下定义跟AndroidX core同名的id,不确定会不会造成其他问题,因此反射获取`proxyListener`,
* 若后续确定同名id不会造成其他问题,或者有其他办法解决爆红问题,则去除反射实现。
*
* ```
* private static class Impl21OnApplyWindowInsetsListener implements
* View.OnApplyWindowInsetsListener {
Expand All @@ -216,13 +207,8 @@ private object InsetsCompatReflection : Reflection {
* ```
*/
fun View.getLastInsetsFromProxyListener(): WindowInsetsCompat? {
val mKeyedTags = mKeyedTagsField?.get(this) as? SparseArray<*> ?: return null
for (index in 0 until mKeyedTags.size()) {
val value = mKeyedTags.valueAt(index)
if (!value.javaClass.isAssignableFrom(proxyListenerClass!!)) continue
mLastInsetsField?.get(value)?.let { it as? WindowInsetsCompat }?.let { return it }
}
return null
val proxyListener = getTag(androidx.core.R.id.tag_window_insets_animation_callback)
return proxyListener?.let { mLastInsetsField?.get(it) as? WindowInsetsCompat }
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,21 +96,21 @@ internal class SystemBarContainer(context: Context) : FrameLayout(context) {
}

override fun onApplyWindowInsets(insets: WindowInsets): WindowInsets {
val applyInsets = insets.toWindowInsetsCompat(this)
var typeMask = 0
var pendingTop = 0
var pendingBottom = 0
if (statusBarEdgeToEdge == EdgeToEdge.Disabled) {
var paddingTop = 0
var paddingBottom = 0
val applyInsets = insets.toWindowInsetsCompat(this)
if (statusBarEdgeToEdge === EdgeToEdge.Disabled) {
typeMask = typeMask or statusBars()
pendingTop = applyInsets.statusBarHeight
paddingTop = applyInsets.statusBarHeight
}
if (navigationBarEdgeToEdge == EdgeToEdge.Disabled
|| (navigationBarEdgeToEdge == EdgeToEdge.Gesture
if (navigationBarEdgeToEdge === EdgeToEdge.Disabled
|| (navigationBarEdgeToEdge === EdgeToEdge.Gesture
&& !applyInsets.isGestureNavigationBar(this))) {
typeMask = typeMask or navigationBars()
pendingBottom = applyInsets.navigationBarHeight
paddingBottom = applyInsets.navigationBarHeight
}
updatePadding(top = pendingTop, bottom = pendingBottom)
updatePadding(top = paddingTop, bottom = paddingBottom)
return applyInsets.consumeInsets(typeMask).toWindowInsets()!!
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
package com.xiaocydx.insets.systembar

import android.view.Window
import androidx.core.view.WindowInsetsCompat.Type.ime
import androidx.core.view.WindowInsetsCompat.Type.systemBars
import androidx.core.view.WindowInsetsCompat.Type.navigationBars
import androidx.core.view.WindowInsetsCompat.Type.statusBars
import com.xiaocydx.insets.disableDecorFitsSystemWindowsInternal

internal val Window.initialState: WindowInitialState
Expand All @@ -45,5 +45,5 @@ internal fun Window.recordSystemBarInitialColor() {
}

internal fun Window.disableDecorFitsSystemWindows() {
disableDecorFitsSystemWindowsInternal(consumeTypeMask = systemBars() or ime())
disableDecorFitsSystemWindowsInternal(consumeTypeMask = statusBars() or navigationBars())
}
9 changes: 5 additions & 4 deletions insets/src/main/kotlin/com/xiaocydx/insets/Compcat.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,9 @@ import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsAnimationCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsCompat.Type.InsetsType
import androidx.core.view.WindowInsetsControllerCompat

/**
* 禁用`window.decorView`实现的消费和间距逻辑,让视图树自行处理[WindowInsets]
* 禁用`window.decorView`实现的消费逻辑和间距逻辑,让视图树自行处理[WindowInsets]
*/
fun Window.disableDecorFitsSystemWindows() {
disableDecorFitsSystemWindowsInternal(consumeTypeMask = 0)
Expand All @@ -41,8 +40,10 @@ fun Window.setDecorFitsSystemWindowsCompat(decorFitsSystemWindows: Boolean) {
WindowCompat.setDecorFitsSystemWindows(this, decorFitsSystemWindows)
}

fun Window.createWindowInsetsControllerCompat(editText: EditText) =
WindowInsetsControllerCompat(this, editText)
/**
* Android 11以下,`WindowInsetsControllerCompat.show(ime())`需要[view]为[EditText]
*/
fun Window.getInsetsControllerCompat(view: View) = WindowCompat.getInsetsController(this, view)

fun View.getRootWindowInsetsCompat() = ViewCompat.getRootWindowInsets(this)

Expand Down
21 changes: 12 additions & 9 deletions insets/src/main/kotlin/com/xiaocydx/insets/Insetter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package com.xiaocydx.insets

import android.graphics.Rect
import android.os.Build.VERSION
import android.view.View
import android.view.ViewGroup
import android.view.WindowInsets
Expand Down Expand Up @@ -91,20 +92,22 @@ fun WindowInsetsCompat.getImeOffset(view: View): Int {
fun WindowInsetsCompat.consumeInsets(@InsetsType typeMask: Int): WindowInsetsCompat {
if (typeMask == 0) return this
var builder = WindowInsetsCompat.Builder(this)
builder.setInsets(typeMask, Insets.NONE)
if (typeMask != ime()) {
// 当typeMask等于ime()时,会抛出IllegalArgumentException
builder.setInsetsIgnoringVisibility(typeMask, Insets.NONE)
}
if (VERSION.SDK_INT < 30) {
// Android 11以下需要修正stableInsets,getInsetsIgnoringVisibility()才返回Insets.NONE
builder.setStableInsets(getInsets(systemBars() and typeMask.inv()))
}
builder.setInsets(typeMask, Insets.NONE)
val systemWindowInsets = getInsets(systemBars() or ime() and typeMask.inv())
if (!systemWindowInsets.isEmpty) {
// Android 11以下的systemWindowInsets包含ime,但在调用builder.setInsets()后,
// builder.build()会替换systemWindowInsets,只剩下statusBars和navigationBars,
// 这会导致判断systemWindowInsets的代码出现异常,因此需要修正systemWindowInsets。
builder = WindowInsetsCompat.Builder(builder.build())
builder.setSystemWindowInsets(systemWindowInsets)
val systemWindowInsets = getInsets(systemBars() or ime() and typeMask.inv())
if (!systemWindowInsets.isEmpty) {
// Android 11以下的systemWindowInsets包含ime,但在调用builder.setInsets()后,
// builder.build()会替换systemWindowInsets,只剩下statusBars和navigationBars,
// 这会导致判断systemWindowInsets的代码出现异常,因此需要修正systemWindowInsets。
builder = WindowInsetsCompat.Builder(builder.build())
builder.setSystemWindowInsets(systemWindowInsets)
}
}
return builder.build()
}
Expand Down

0 comments on commit cea8630

Please sign in to comment.