Switch to the WindowInsetsAnimationCompat api

Replace the use of WindowInsetsAnimation with WindowInsetsAnimationCompat; the former was only introdcued in api 30 and caused a crash on older versions of Android.

Fixes https://github.com/godotengine/godot/issues/91773
This commit is contained in:
Fredia Huya-Kouadio 2024-05-13 00:59:03 -07:00
parent bdc0316217
commit ab4fbbcaa7

View file

@ -38,7 +38,6 @@ import android.content.pm.PackageManager
import android.content.res.Configuration import android.content.res.Configuration
import android.content.res.Resources import android.content.res.Resources
import android.graphics.Color import android.graphics.Color
import android.graphics.Rect
import android.hardware.Sensor import android.hardware.Sensor
import android.hardware.SensorEvent import android.hardware.SensorEvent
import android.hardware.SensorEventListener import android.hardware.SensorEventListener
@ -46,10 +45,12 @@ import android.hardware.SensorManager
import android.os.* import android.os.*
import android.util.Log import android.util.Log
import android.view.* import android.view.*
import android.view.ViewTreeObserver.OnGlobalLayoutListener
import android.widget.FrameLayout import android.widget.FrameLayout
import androidx.annotation.Keep import androidx.annotation.Keep
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsAnimationCompat
import androidx.core.view.WindowInsetsCompat
import com.google.android.vending.expansion.downloader.* import com.google.android.vending.expansion.downloader.*
import org.godotengine.godot.input.GodotEditText import org.godotengine.godot.input.GodotEditText
import org.godotengine.godot.io.directory.DirectoryAccessHandler import org.godotengine.godot.io.directory.DirectoryAccessHandler
@ -418,58 +419,42 @@ class Godot(private val context: Context) : SensorEventListener {
io?.setEdit(editText) io?.setEdit(editText)
// Listeners for keyboard height. // Listeners for keyboard height.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { val decorView = activity.window.decorView
// Report the height of virtual keyboard as it changes during the animation. // Report the height of virtual keyboard as it changes during the animation.
val decorView = activity.window.decorView ViewCompat.setWindowInsetsAnimationCallback(decorView, object : WindowInsetsAnimationCompat.Callback(DISPATCH_MODE_STOP) {
decorView.setWindowInsetsAnimationCallback(object : WindowInsetsAnimation.Callback(DISPATCH_MODE_STOP) { var startBottom = 0
var startBottom = 0 var endBottom = 0
var endBottom = 0 override fun onPrepare(animation: WindowInsetsAnimationCompat) {
override fun onPrepare(animation: WindowInsetsAnimation) { startBottom = ViewCompat.getRootWindowInsets(decorView)?.getInsets(WindowInsetsCompat.Type.ime())?.bottom ?: 0
startBottom = decorView.rootWindowInsets.getInsets(WindowInsets.Type.ime()).bottom }
}
override fun onStart(animation: WindowInsetsAnimation, bounds: WindowInsetsAnimation.Bounds): WindowInsetsAnimation.Bounds { override fun onStart(animation: WindowInsetsAnimationCompat, bounds: WindowInsetsAnimationCompat.BoundsCompat): WindowInsetsAnimationCompat.BoundsCompat {
endBottom = decorView.rootWindowInsets.getInsets(WindowInsets.Type.ime()).bottom endBottom = ViewCompat.getRootWindowInsets(decorView)?.getInsets(WindowInsetsCompat.Type.ime())?.bottom ?: 0
return bounds return bounds
} }
override fun onProgress(windowInsets: WindowInsets, list: List<WindowInsetsAnimation>): WindowInsets { override fun onProgress(windowInsets: WindowInsetsCompat, animationsList: List<WindowInsetsAnimationCompat>): WindowInsetsCompat {
// Find the IME animation. // Find the IME animation.
var imeAnimation: WindowInsetsAnimation? = null var imeAnimation: WindowInsetsAnimationCompat? = null
for (animation in list) { for (animation in animationsList) {
if (animation.typeMask and WindowInsets.Type.ime() != 0) { if (animation.typeMask and WindowInsetsCompat.Type.ime() != 0) {
imeAnimation = animation imeAnimation = animation
break break
}
}
// Update keyboard height based on IME animation.
if (imeAnimation != null) {
val interpolatedFraction = imeAnimation.interpolatedFraction
// Linear interpolation between start and end values.
val keyboardHeight = startBottom * (1.0f - interpolatedFraction) + endBottom * interpolatedFraction
GodotLib.setVirtualKeyboardHeight(keyboardHeight.toInt())
}
return windowInsets
}
override fun onEnd(animation: WindowInsetsAnimation) {}
})
} else {
// Infer the virtual keyboard height using visible area.
renderView?.view?.viewTreeObserver?.addOnGlobalLayoutListener(object : OnGlobalLayoutListener {
// Don't allocate a new Rect every time the callback is called.
val visibleSize = Rect()
override fun onGlobalLayout() {
renderView?.let {
val surfaceView = it.view
surfaceView.getWindowVisibleDisplayFrame(visibleSize)
val keyboardHeight = surfaceView.height - visibleSize.bottom
GodotLib.setVirtualKeyboardHeight(keyboardHeight)
} }
} }
})
} // Update keyboard height based on IME animation.
if (imeAnimation != null) {
val interpolatedFraction = imeAnimation.interpolatedFraction
// Linear interpolation between start and end values.
val keyboardHeight = startBottom * (1.0f - interpolatedFraction) + endBottom * interpolatedFraction
GodotLib.setVirtualKeyboardHeight(keyboardHeight.toInt())
}
return windowInsets
}
override fun onEnd(animation: WindowInsetsAnimationCompat) {}
})
if (host == primaryHost) { if (host == primaryHost) {
renderView?.queueOnRenderThread { renderView?.queueOnRenderThread {