Observe content view layout natively on Android too
Same approach as the iOS KVO change: use View.OnLayoutChangeListener on the content view to detect height changes purely on the native side. This eliminates the setTimeout → updateLayout() JS bridge hack that was a known workaround for async timing issues on Android. The onLayout callback in JS is now only used for the iOS 15 fallback height measurement. All other height observation is native. https://claude.ai/code/session_01Rp7ef1h3fKh6fhStcjqLJ5
This commit is contained in:
+35
@@ -36,6 +36,10 @@ class BottomSheetView(
|
||||
private var eventDispatcher: EventDispatcher? = null
|
||||
private var isKeyboardVisible: Boolean = false
|
||||
|
||||
// Native content height observation (eliminates JS bridge round-trip)
|
||||
private var contentLayoutListener: View.OnLayoutChangeListener? = null
|
||||
private var observedContentView: View? = null
|
||||
|
||||
private val screenHeight =
|
||||
context.resources.displayMetrics.heightPixels
|
||||
.toFloat()
|
||||
@@ -129,6 +133,7 @@ class BottomSheetView(
|
||||
}
|
||||
|
||||
private fun destroy() {
|
||||
this.stopObservingContentHeight()
|
||||
this.isClosing = false
|
||||
this.isOpen = false
|
||||
this.dialog = null
|
||||
@@ -245,6 +250,7 @@ class BottomSheetView(
|
||||
this.isOpening = true
|
||||
dialog.show()
|
||||
this.dialog = dialog
|
||||
this.startObservingContentHeight()
|
||||
|
||||
ViewCompat.setOnApplyWindowInsetsListener(dialogRootViewGroup) { view, insets ->
|
||||
val imeVisible = insets.isVisible(WindowInsetsCompat.Type.ime())
|
||||
@@ -310,6 +316,35 @@ class BottomSheetView(
|
||||
this.dialog?.dismiss()
|
||||
}
|
||||
|
||||
// Observe the content view's layout changes so that height updates are detected
|
||||
// purely on the native side, without a JS bridge round-trip through onLayout.
|
||||
private fun startObservingContentHeight() {
|
||||
stopObservingContentHeight()
|
||||
|
||||
val innerViewGroup = this.innerView as? ViewGroup ?: return
|
||||
val contentView = innerViewGroup.getChildAt(0) ?: return
|
||||
|
||||
val listener = View.OnLayoutChangeListener { _, _, top, _, bottom, _, _, oldTop, _, oldBottom ->
|
||||
val newHeight = bottom - top
|
||||
val oldHeight = oldBottom - oldTop
|
||||
if (newHeight != oldHeight && newHeight > 0 && (isOpen || isOpening) && !isClosing) {
|
||||
updateLayout()
|
||||
}
|
||||
}
|
||||
|
||||
contentView.addOnLayoutChangeListener(listener)
|
||||
this.contentLayoutListener = listener
|
||||
this.observedContentView = contentView
|
||||
}
|
||||
|
||||
private fun stopObservingContentHeight() {
|
||||
contentLayoutListener?.let { listener ->
|
||||
observedContentView?.removeOnLayoutChangeListener(listener)
|
||||
}
|
||||
contentLayoutListener = null
|
||||
observedContentView = null
|
||||
}
|
||||
|
||||
// Util
|
||||
|
||||
private fun getContentHeight(): Float {
|
||||
|
||||
Reference in New Issue
Block a user