@@ -2,25 +2,23 @@ package com.lodev09.truesheet
22
33import android.annotation.SuppressLint
44import android.graphics.Color
5- import android.graphics.drawable.ShapeDrawable
6- import android.graphics.drawable.shapes.RoundRectShape
5+ import android.graphics.Rect
76import android.view.View
87import android.view.ViewGroup
98import android.view.WindowManager
9+ import androidx.constraintlayout.widget.ConstraintLayout
10+ import androidx.core.graphics.drawable.toDrawable
1011import com.facebook.react.uimanager.ThemedReactContext
1112import com.google.android.material.bottomsheet.BottomSheetBehavior
1213import com.google.android.material.bottomsheet.BottomSheetDialog
13- import com.lodev09.truesheet.core.KeyboardManager
14- import com.lodev09.truesheet.core.RootSheetView
1514import com.lodev09.truesheet.core.Utils
1615
1716data class SizeInfo (val index : Int , val value : Float )
1817
1918@SuppressLint(" ClickableViewAccessibility" )
20- class TrueSheetDialog (private val reactContext : ThemedReactContext , private val rootSheetView : RootSheetView ) :
19+ class TrueSheetDialog (private val reactContext : ThemedReactContext , private val rootSheetView : ViewGroup ) :
2120 BottomSheetDialog (reactContext) {
2221
23- private var keyboardManager = KeyboardManager (reactContext)
2422 private var windowAnimation: Int = 0
2523
2624 // First child of the rootSheetView
@@ -31,8 +29,8 @@ class TrueSheetDialog(private val reactContext: ThemedReactContext, private val
3129 null
3230 }
3331
34- private val sheetContainerView: ViewGroup ?
35- get() = rootSheetView .parent?.let { it as ? ViewGroup }
32+ val sheetContainerView: ViewGroup ?
33+ get() = proxyView .parent?.let { it as ? ViewGroup }
3634
3735 /* *
3836 * Specify whether the sheet background is dimmed.
@@ -52,6 +50,7 @@ class TrueSheetDialog(private val reactContext: ThemedReactContext, private val
5250 var maxScreenHeight = 0
5351
5452 var contentHeight = 0
53+ var headerHeight = 0
5554 var footerHeight = 0
5655 var maxSheetHeight: Int? = null
5756
@@ -70,24 +69,25 @@ class TrueSheetDialog(private val reactContext: ThemedReactContext, private val
7069 behavior.isHideable = value
7170 }
7271
73- var cornerRadius: Float = 0f
74- var backgroundColor: Int = Color .WHITE
72+ // 1st child is the header view
73+ val headerView: ViewGroup ?
74+ get() = containerView?.getChildAt(0 ) as ? ViewGroup
7575
76- // 1st child is the content view
76+ // 2nd child is the content view
7777 val contentView: ViewGroup ?
78- get() = containerView?.getChildAt(0 ) as ? ViewGroup
78+ get() = containerView?.getChildAt(1 ) as ? ViewGroup
7979
80- // 2nd child is the footer view
80+ // 3rd child is the footer view
8181 val footerView: ViewGroup ?
82- get() = containerView?.getChildAt(1 ) as ? ViewGroup
82+ get() = containerView?.getChildAt(2 ) as ? ViewGroup
8383
8484 var sizes: Array <Any > = arrayOf(" medium" , " large" )
8585
86- init {
87- setContentView(rootSheetView)
86+ private val proxyView = ConstraintLayout (reactContext)
8887
89- sheetContainerView?.setBackgroundColor(backgroundColor)
90- sheetContainerView?.clipToOutline = true
88+ init {
89+ proxyView.addView(rootSheetView)
90+ setContentView(proxyView)
9191
9292 // Setup window params to adjust layout based on Keyboard state
9393 window?.apply {
@@ -99,45 +99,37 @@ class TrueSheetDialog(private val reactContext: ThemedReactContext, private val
9999 maxScreenHeight = Utils .screenHeight(reactContext, edgeToEdge)
100100 }
101101
102+ fun getVisibleContentDimensions () : Rect {
103+ val rect = Rect ()
104+ proxyView.getGlobalVisibleRect(rect)
105+ return rect
106+ }
107+
102108 override fun getEdgeToEdgeEnabled (): Boolean = edgeToEdge || super .getEdgeToEdgeEnabled()
103109
104110 override fun onStart () {
105111 super .onStart()
106112
113+ // We don't want any of the background to be rendered, it should be completely
114+ // handled by the React side of things.
115+ val transparent = Color .TRANSPARENT .toDrawable()
116+ sheetContainerView?.background = transparent
117+ proxyView.background = transparent
118+ rootSheetView.background = transparent
119+
107120 if (edgeToEdge) {
121+ super .getEdgeToEdgeEnabled()
122+
108123 window?.apply {
109124 setFlags(
110125 WindowManager .LayoutParams .FLAG_LAYOUT_NO_LIMITS ,
111126 WindowManager .LayoutParams .FLAG_LAYOUT_NO_LIMITS
112127 )
113-
114128 decorView.systemUiVisibility = View .SYSTEM_UI_FLAG_LAYOUT_STABLE or View .SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
115129 }
116130 }
117131 }
118132
119- /* *
120- * Setup background color and corner radius.
121- */
122- fun setupBackground () {
123- val outerRadii = floatArrayOf(
124- cornerRadius,
125- cornerRadius,
126- cornerRadius,
127- cornerRadius,
128- 0f ,
129- 0f ,
130- 0f ,
131- 0f
132- )
133-
134- val background = ShapeDrawable (RoundRectShape (outerRadii, null , null ))
135-
136- // Use current background color
137- background.paint.color = backgroundColor
138- sheetContainerView?.background = background
139- }
140-
141133 /* *
142134 * Setup dimmed sheet.
143135 * `dimmedIndex` will further customize the dimming behavior.
@@ -199,14 +191,6 @@ class TrueSheetDialog(private val reactContext: ThemedReactContext, private val
199191 }
200192 }
201193
202- fun positionFooter () {
203- footerView?.let { footer ->
204- sheetContainerView?.let { container ->
205- footer.y = (maxScreenHeight - container.top - footerHeight).toFloat()
206- }
207- }
208- }
209-
210194 /* *
211195 * Set the state based for the given size index.
212196 */
@@ -226,7 +210,7 @@ class TrueSheetDialog(private val reactContext: ThemedReactContext, private val
226210
227211 is String -> {
228212 when (size) {
229- " auto" -> contentHeight + footerHeight
213+ " auto" -> minOf( contentHeight + headerHeight + footerHeight, maxScreenHeight * 10 / 9 )
230214
231215 " large" -> maxScreenHeight
232216
@@ -287,34 +271,6 @@ class TrueSheetDialog(private val reactContext: ThemedReactContext, private val
287271 else -> BottomSheetBehavior .STATE_HIDDEN
288272 }
289273
290- /* *
291- * Handle keyboard state changes and adjust maxScreenHeight (sheet max height) accordingly.
292- * Also update footer's Y position.
293- */
294- fun registerKeyboardManager () {
295- keyboardManager.registerKeyboardListener(object : KeyboardManager .OnKeyboardChangeListener {
296- override fun onKeyboardStateChange (isVisible : Boolean , visibleHeight : Int? ) {
297- maxScreenHeight = when (isVisible) {
298- true -> visibleHeight ? : 0
299- else -> Utils .screenHeight(reactContext, edgeToEdge)
300- }
301-
302- positionFooter()
303- }
304- })
305- }
306-
307- fun setOnSizeChangeListener (listener : (w: Int , h: Int ) -> Unit ) {
308- rootSheetView.sizeChangeListener = listener
309- }
310-
311- /* *
312- * Remove keyboard listener.
313- */
314- fun unregisterKeyboardManager () {
315- keyboardManager.unregisterKeyboardListener()
316- }
317-
318274 /* *
319275 * Configure the sheet based from the size preference.
320276 */
@@ -344,10 +300,16 @@ class TrueSheetDialog(private val reactContext: ThemedReactContext, private val
344300
345301 setPeekHeight(getSizeHeight(sizes[0 ]), isShowing)
346302
347- halfExpandedRatio = minOf(getSizeHeight(sizes[1 ]).toFloat() / maxScreenHeight.toFloat(), 1.0f )
303+ // Android crashes if 1.0f is specified for the half-expanded ratio
304+ val ratio = minOf(getSizeHeight(sizes[1 ]).toFloat() / maxScreenHeight.toFloat(), 0.99f )
305+ halfExpandedRatio = ratio
348306 maxHeight = getSizeHeight(sizes[2 ])
349307 }
350308 }
309+ // Since the React content no longer drives the height calculations, update
310+ // the proxy view's height to take all the available space.
311+ proxyView.minHeight = maxHeight
312+ proxyView.maxHeight = maxHeight
351313 }
352314 }
353315
0 commit comments