Skip to content

Commit

Permalink
fix: update SafeAreaProvider to use ViewCompat.setOnApplyWindowInsets…
Browse files Browse the repository at this point in the history
…Listener instead of onPreDraw() to detect inset values more reliably in SDK35.
  • Loading branch information
Casey Langen committed Feb 21, 2025
1 parent fdb0e78 commit 9597c93
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 27 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
package com.th3rdwave.safeareacontext

data class EdgeInsets(val top: Float, val right: Float, val bottom: Float, val left: Float)
data class EdgeInsets(val top: Float, val right: Float, val bottom: Float, val left: Float) {
override fun toString(): String {
return "(top=${top}, right=${right}, bottom=${bottom}, left=${left})"
}
}
Original file line number Diff line number Diff line change
@@ -1,47 +1,63 @@
package com.th3rdwave.safeareacontext

import android.content.Context
import android.util.Log
import android.view.ViewGroup
import android.view.ViewTreeObserver
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.facebook.react.views.view.ReactViewGroup

const val DEBUG = false

typealias OnInsetsChangeHandler = (view: SafeAreaProvider, insets: EdgeInsets, frame: Rect) -> Unit

class SafeAreaProvider(context: Context?) :
ReactViewGroup(context), ViewTreeObserver.OnPreDrawListener {
class SafeAreaProvider(context: Context?) : ReactViewGroup(context) {
private var mInsetsChangeHandler: OnInsetsChangeHandler? = null
private var mLastInsets: EdgeInsets? = null
private var mLastFrame: Rect? = null
private var mCurrentInsets: EdgeInsets = EdgeInsets(0.0f, 0.0f, 0.0f, 0.0f)

private fun maybeUpdateInsets() {
val insetsChangeHandler = mInsetsChangeHandler ?: return
val edgeInsets = getSafeAreaInsets(this) ?: return
val frame = getFrame(rootView as ViewGroup, this) ?: return
if (mLastInsets != edgeInsets || mLastFrame != frame) {
insetsChangeHandler(this, edgeInsets, frame)
mLastInsets = edgeInsets
mLastFrame = frame
init {
ViewCompat.setOnApplyWindowInsetsListener(this) { _, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())

mCurrentInsets = EdgeInsets(
systemBars.top.toFloat(),
systemBars.left.toFloat(),
systemBars.bottom.toFloat(),
systemBars.right.toFloat())

if (DEBUG) {
Log.d("SafeAreaProvider", "calculated insets: $mCurrentInsets")
}

sendInsetValuesToJs()

insets
}
}

override fun onAttachedToWindow() {
super.onAttachedToWindow()
viewTreeObserver.addOnPreDrawListener(this)
maybeUpdateInsets()
}
private fun sendInsetValuesToJs() {
val insetsChangeHandler = mInsetsChangeHandler ?: return
val frame = getFrame(rootView as ViewGroup, this) ?: return

override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
viewTreeObserver.removeOnPreDrawListener(this)
}
if (DEBUG) {
Log.d("SafeAreaProvider", "emitting updated insets: $mCurrentInsets")
}

override fun onPreDraw(): Boolean {
maybeUpdateInsets()
return true
insetsChangeHandler(this, mCurrentInsets, frame)
}

fun setOnInsetsChangeHandler(handler: OnInsetsChangeHandler?) {
mInsetsChangeHandler = handler
maybeUpdateInsets()
sendInsetValuesToJs()
}

override fun onAttachedToWindow() {
super.onAttachedToWindow()

if (DEBUG) {
Log.d("SafeAreaProvider", "attached to window")
}

requestApplyInsets()
}
}

0 comments on commit 9597c93

Please # to comment.