@lodev09/react-native-true-sheet 3.3.0-beta.2 → 3.3.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -29,7 +29,8 @@ import com.google.android.material.bottomsheet.BottomSheetDialog
|
|
|
29
29
|
import com.lodev09.truesheet.core.GrabberOptions
|
|
30
30
|
import com.lodev09.truesheet.core.RNScreensFragmentObserver
|
|
31
31
|
import com.lodev09.truesheet.core.TrueSheetGrabberView
|
|
32
|
-
import com.lodev09.truesheet.core.
|
|
32
|
+
import com.lodev09.truesheet.core.TrueSheetKeyboardObserver
|
|
33
|
+
import com.lodev09.truesheet.core.TrueSheetKeyboardObserverDelegate
|
|
33
34
|
import com.lodev09.truesheet.utils.ScreenUtils
|
|
34
35
|
|
|
35
36
|
data class DetentInfo(val index: Int, val position: Float)
|
|
@@ -224,7 +225,7 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
224
225
|
|
|
225
226
|
window?.apply {
|
|
226
227
|
windowAnimation = attributes.windowAnimations
|
|
227
|
-
// Disable default keyboard avoidance - sheet handles it via
|
|
228
|
+
// Disable default keyboard avoidance - sheet handles it via setupKeyboardObserver
|
|
228
229
|
setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING)
|
|
229
230
|
}
|
|
230
231
|
|
|
@@ -255,7 +256,7 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
255
256
|
setOnDismissListener(null)
|
|
256
257
|
}
|
|
257
258
|
|
|
258
|
-
|
|
259
|
+
cleanupKeyboardObserver()
|
|
259
260
|
cleanupModalObserver()
|
|
260
261
|
sheetContainer?.removeView(this)
|
|
261
262
|
|
|
@@ -274,7 +275,7 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
274
275
|
resetAnimation()
|
|
275
276
|
setupBackground()
|
|
276
277
|
setupGrabber()
|
|
277
|
-
|
|
278
|
+
setupKeyboardObserver()
|
|
278
279
|
|
|
279
280
|
sheetContainer?.post {
|
|
280
281
|
bottomSheetView?.let { emitChangePositionDelegate(it, realtime = false) }
|
|
@@ -568,18 +569,23 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
568
569
|
bottomSheet.addView(grabberView)
|
|
569
570
|
}
|
|
570
571
|
|
|
571
|
-
private var
|
|
572
|
+
private var keyboardObserver: TrueSheetKeyboardObserver? = null
|
|
572
573
|
|
|
573
|
-
|
|
574
|
-
fun setupKeyboardHandler() {
|
|
574
|
+
fun setupKeyboardObserver() {
|
|
575
575
|
val bottomSheet = bottomSheetView ?: return
|
|
576
|
-
|
|
577
|
-
|
|
576
|
+
keyboardObserver = TrueSheetKeyboardObserver(bottomSheet, reactContext).apply {
|
|
577
|
+
delegate = object : TrueSheetKeyboardObserverDelegate {
|
|
578
|
+
override fun keyboardHeightDidChange(height: Int) {
|
|
579
|
+
setupSheetDetents()
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
start()
|
|
583
|
+
}
|
|
578
584
|
}
|
|
579
585
|
|
|
580
|
-
fun
|
|
581
|
-
|
|
582
|
-
|
|
586
|
+
fun cleanupKeyboardObserver() {
|
|
587
|
+
keyboardObserver?.stop()
|
|
588
|
+
keyboardObserver = null
|
|
583
589
|
}
|
|
584
590
|
|
|
585
591
|
fun setupBackground() {
|
|
@@ -632,7 +638,7 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
632
638
|
val sheetTop = bottomSheet.top
|
|
633
639
|
|
|
634
640
|
// Footer Y relative to sheet: place at bottom of sheet container minus footer height
|
|
635
|
-
var footerY = (sheetHeight - sheetTop - footerHeight).toFloat()
|
|
641
|
+
var footerY = (sheetHeight - sheetTop - footerHeight - keyboardHeight).toFloat()
|
|
636
642
|
|
|
637
643
|
if (slideOffset != null && slideOffset < 0) {
|
|
638
644
|
footerY -= (footerHeight * slideOffset)
|
|
@@ -806,16 +812,17 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
806
812
|
// MARK: - Detent Calculations
|
|
807
813
|
// ====================================================================
|
|
808
814
|
|
|
815
|
+
private val keyboardHeight: Int
|
|
816
|
+
get() = keyboardObserver?.currentHeight ?: 0
|
|
817
|
+
|
|
809
818
|
private fun getDetentHeight(detent: Double): Int {
|
|
810
|
-
val height
|
|
811
|
-
|
|
812
|
-
contentHeight + headerHeight + contentBottomInset
|
|
819
|
+
val height = if (detent == -1.0) {
|
|
820
|
+
contentHeight + headerHeight + contentBottomInset + keyboardHeight
|
|
813
821
|
} else {
|
|
814
822
|
if (detent <= 0.0 || detent > 1.0) {
|
|
815
823
|
throw IllegalArgumentException("TrueSheet: detent fraction ($detent) must be between 0 and 1")
|
|
816
824
|
}
|
|
817
|
-
|
|
818
|
-
(detent * screenHeight).toInt() + contentBottomInset
|
|
825
|
+
(detent * screenHeight).toInt() + contentBottomInset + keyboardHeight
|
|
819
826
|
}
|
|
820
827
|
|
|
821
828
|
val maxAllowedHeight = screenHeight + contentBottomInset
|
|
@@ -9,25 +9,25 @@ import androidx.core.view.WindowInsetsAnimationCompat
|
|
|
9
9
|
import androidx.core.view.WindowInsetsCompat
|
|
10
10
|
import com.facebook.react.uimanager.ThemedReactContext
|
|
11
11
|
|
|
12
|
+
interface TrueSheetKeyboardObserverDelegate {
|
|
13
|
+
fun keyboardHeightDidChange(height: Int)
|
|
14
|
+
}
|
|
15
|
+
|
|
12
16
|
/**
|
|
13
|
-
*
|
|
14
|
-
* Uses WindowInsetsAnimationCompat
|
|
15
|
-
* falls back to ViewTreeObserver on Activity's decor view for API 29 and below.
|
|
16
|
-
*
|
|
17
|
-
* @param targetView The view to translate (typically the bottom sheet)
|
|
18
|
-
* @param reactContext The React context to get the current activity
|
|
19
|
-
* @param topInset The top safe area inset to respect
|
|
17
|
+
* Tracks keyboard height and notifies delegate on changes.
|
|
18
|
+
* Uses WindowInsetsAnimationCompat on API 30+, ViewTreeObserver fallback on older versions.
|
|
20
19
|
*/
|
|
21
|
-
class
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
20
|
+
class TrueSheetKeyboardObserver(private val targetView: View, private val reactContext: ThemedReactContext) {
|
|
21
|
+
|
|
22
|
+
var delegate: TrueSheetKeyboardObserverDelegate? = null
|
|
23
|
+
|
|
24
|
+
var currentHeight: Int = 0
|
|
25
|
+
private set
|
|
26
26
|
|
|
27
27
|
private var globalLayoutListener: ViewTreeObserver.OnGlobalLayoutListener? = null
|
|
28
28
|
private var activityRootView: View? = null
|
|
29
29
|
|
|
30
|
-
fun
|
|
30
|
+
fun start() {
|
|
31
31
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
|
32
32
|
setupAnimationCallback()
|
|
33
33
|
} else {
|
|
@@ -35,7 +35,7 @@ class TrueSheetKeyboardHandler(
|
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
fun
|
|
38
|
+
fun stop() {
|
|
39
39
|
globalLayoutListener?.let { listener ->
|
|
40
40
|
activityRootView?.viewTreeObserver?.removeOnGlobalLayoutListener(listener)
|
|
41
41
|
globalLayoutListener = null
|
|
@@ -44,35 +44,31 @@ class TrueSheetKeyboardHandler(
|
|
|
44
44
|
ViewCompat.setWindowInsetsAnimationCallback(targetView, null)
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
private fun
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
47
|
+
private fun updateHeight(height: Int) {
|
|
48
|
+
if (currentHeight != height) {
|
|
49
|
+
currentHeight = height
|
|
50
|
+
delegate?.keyboardHeightDidChange(height)
|
|
51
|
+
}
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
|
|
54
|
+
private fun getKeyboardHeight(insets: WindowInsetsCompat?): Int = insets?.getInsets(WindowInsetsCompat.Type.ime())?.bottom ?: 0
|
|
55
|
+
|
|
55
56
|
private fun setupAnimationCallback() {
|
|
56
57
|
ViewCompat.setWindowInsetsAnimationCallback(
|
|
57
58
|
targetView,
|
|
58
59
|
object : WindowInsetsAnimationCompat.Callback(DISPATCH_MODE_CONTINUE_ON_SUBTREE) {
|
|
59
|
-
private var
|
|
60
|
-
private var
|
|
61
|
-
|
|
62
|
-
private fun getKeyboardHeight(rootInsets: WindowInsetsCompat?): Int {
|
|
63
|
-
if (rootInsets == null) return 0
|
|
64
|
-
return rootInsets.getInsets(WindowInsetsCompat.Type.ime()).bottom
|
|
65
|
-
}
|
|
60
|
+
private var startHeight = 0
|
|
61
|
+
private var endHeight = 0
|
|
66
62
|
|
|
67
63
|
override fun onPrepare(animation: WindowInsetsAnimationCompat) {
|
|
68
|
-
|
|
64
|
+
startHeight = getKeyboardHeight(ViewCompat.getRootWindowInsets(targetView))
|
|
69
65
|
}
|
|
70
66
|
|
|
71
67
|
override fun onStart(
|
|
72
68
|
animation: WindowInsetsAnimationCompat,
|
|
73
69
|
bounds: WindowInsetsAnimationCompat.BoundsCompat
|
|
74
70
|
): WindowInsetsAnimationCompat.BoundsCompat {
|
|
75
|
-
|
|
71
|
+
endHeight = getKeyboardHeight(ViewCompat.getRootWindowInsets(targetView))
|
|
76
72
|
return bounds
|
|
77
73
|
}
|
|
78
74
|
|
|
@@ -82,23 +78,21 @@ class TrueSheetKeyboardHandler(
|
|
|
82
78
|
} ?: return insets
|
|
83
79
|
|
|
84
80
|
val fraction = imeAnimation.interpolatedFraction
|
|
85
|
-
val
|
|
86
|
-
|
|
81
|
+
val currentHeight = (startHeight + (endHeight - startHeight) * fraction).toInt()
|
|
82
|
+
updateHeight(currentHeight)
|
|
87
83
|
|
|
88
84
|
return insets
|
|
89
85
|
}
|
|
90
86
|
|
|
91
87
|
override fun onEnd(animation: WindowInsetsAnimationCompat) {
|
|
92
|
-
|
|
88
|
+
updateHeight(getKeyboardHeight(ViewCompat.getRootWindowInsets(targetView)))
|
|
93
89
|
}
|
|
94
90
|
}
|
|
95
91
|
)
|
|
96
92
|
}
|
|
97
93
|
|
|
98
|
-
/** API 29 and below fallback using ViewTreeObserver on Activity's root view */
|
|
99
94
|
private fun setupLegacyListener() {
|
|
100
95
|
val rootView = reactContext.currentActivity?.window?.decorView?.rootView ?: return
|
|
101
|
-
|
|
102
96
|
activityRootView = rootView
|
|
103
97
|
|
|
104
98
|
globalLayoutListener = ViewTreeObserver.OnGlobalLayoutListener {
|
|
@@ -108,11 +102,7 @@ class TrueSheetKeyboardHandler(
|
|
|
108
102
|
val screenHeight = rootView.height
|
|
109
103
|
val keyboardHeight = screenHeight - rect.bottom
|
|
110
104
|
|
|
111
|
-
if (keyboardHeight > screenHeight * 0.15)
|
|
112
|
-
applyTranslation(keyboardHeight)
|
|
113
|
-
} else {
|
|
114
|
-
applyTranslation(0)
|
|
115
|
-
}
|
|
105
|
+
updateHeight(if (keyboardHeight > screenHeight * 0.15) keyboardHeight else 0)
|
|
116
106
|
}
|
|
117
107
|
|
|
118
108
|
rootView.viewTreeObserver.addOnGlobalLayoutListener(globalLayoutListener)
|
package/package.json
CHANGED