@lodev09/react-native-true-sheet 3.6.9 → 3.6.10

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.
@@ -248,6 +248,10 @@ class TrueSheetView(private val reactContext: ThemedReactContext) :
248
248
  viewController.insetAdjustment = insetAdjustment
249
249
  }
250
250
 
251
+ fun setScrollable(scrollable: Boolean) {
252
+ viewController.scrollable = scrollable
253
+ }
254
+
251
255
  // ==================== State Management ====================
252
256
 
253
257
  /**
@@ -170,6 +170,11 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
170
170
  override var grabberOptions: GrabberOptions? = null
171
171
  override var sheetBackgroundColor: Int? = null
172
172
  var insetAdjustment: String = "automatic"
173
+ var scrollable: Boolean = false
174
+ set(value) {
175
+ field = value
176
+ coordinatorLayout?.scrollable = value
177
+ }
173
178
 
174
179
  override var sheetCornerRadius: Float = DEFAULT_CORNER_RADIUS.dpToPx()
175
180
  set(value) {
@@ -297,6 +302,7 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
297
302
  // Create coordinator layout
298
303
  coordinatorLayout = TrueSheetCoordinatorLayout(reactContext).apply {
299
304
  delegate = this@TrueSheetViewController
305
+ scrollable = this@TrueSheetViewController.scrollable
300
306
  }
301
307
 
302
308
  sheetView = TrueSheetBottomSheetView(reactContext).apply {
@@ -190,7 +190,7 @@ class TrueSheetViewManager :
190
190
 
191
191
  @ReactProp(name = "scrollable", defaultBoolean = false)
192
192
  override fun setScrollable(view: TrueSheetView, value: Boolean) {
193
- // iOS-specific prop - no-op on Android
193
+ view.setScrollable(value)
194
194
  }
195
195
 
196
196
  @ReactProp(name = "pageSizing", defaultBoolean = true)
@@ -2,7 +2,10 @@ package com.lodev09.truesheet.core
2
2
 
3
3
  import android.annotation.SuppressLint
4
4
  import android.content.Context
5
- import android.view.View
5
+ import android.view.MotionEvent
6
+ import android.view.ViewConfiguration
7
+ import android.view.ViewGroup
8
+ import android.widget.ScrollView
6
9
  import androidx.coordinatorlayout.widget.CoordinatorLayout
7
10
  import com.facebook.react.uimanager.PointerEvents
8
11
  import com.facebook.react.uimanager.ReactPointerEventsView
@@ -22,15 +25,19 @@ class TrueSheetCoordinatorLayout(context: Context) :
22
25
  ReactPointerEventsView {
23
26
 
24
27
  var delegate: TrueSheetCoordinatorLayoutDelegate? = null
28
+ var scrollable: Boolean = false
29
+
30
+ private val touchSlop: Int = ViewConfiguration.get(context).scaledTouchSlop
31
+ private var dragging = false
32
+ private var initialY = 0f
33
+ private var activePointerId = 0
25
34
 
26
35
  init {
27
- // Fill the entire screen
28
36
  layoutParams = LayoutParams(
29
37
  LayoutParams.MATCH_PARENT,
30
38
  LayoutParams.MATCH_PARENT
31
39
  )
32
40
 
33
- // Ensure we don't clip the sheet during animations
34
41
  clipChildren = false
35
42
  clipToPadding = false
36
43
  }
@@ -46,10 +53,87 @@ class TrueSheetCoordinatorLayout(context: Context) :
46
53
  delegate?.coordinatorLayoutDidLayout(changed)
47
54
  }
48
55
 
49
- /**
50
- * Allow pointer events to pass through to underlying views.
51
- * The DimView and BottomSheetView handle their own touch interception.
52
- */
53
56
  override val pointerEvents: PointerEvents
54
57
  get() = PointerEvents.BOX_NONE
58
+
59
+ /**
60
+ * Intercepts touch events for ScrollViews that can't scroll (content < viewport),
61
+ * allowing the sheet to be dragged in these cases.
62
+ *
63
+ * TODO: Remove this workaround once NestedScrollView is merged into react-native core.
64
+ * See: https://github.com/facebook/react-native/pull/44099
65
+ */
66
+ override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
67
+ if (!scrollable) {
68
+ return super.onInterceptTouchEvent(ev)
69
+ }
70
+
71
+ val scrollView = findScrollView(this)
72
+ val cannotScroll = scrollView != null &&
73
+ scrollView.scrollY == 0 &&
74
+ !scrollView.canScrollVertically(1)
75
+
76
+ if (cannotScroll) {
77
+ when (ev.action and MotionEvent.ACTION_MASK) {
78
+ MotionEvent.ACTION_DOWN -> {
79
+ dragging = false
80
+ initialY = ev.y
81
+ activePointerId = ev.getPointerId(0)
82
+ }
83
+
84
+ MotionEvent.ACTION_MOVE -> {
85
+ val pointerIndex = ev.findPointerIndex(activePointerId)
86
+ if (pointerIndex != -1) {
87
+ val y = ev.getY(pointerIndex)
88
+ val deltaY = initialY - y
89
+ if (kotlin.math.abs(deltaY) > touchSlop) {
90
+ dragging = true
91
+ parent?.requestDisallowInterceptTouchEvent(true)
92
+ }
93
+ }
94
+ }
95
+
96
+ MotionEvent.ACTION_UP,
97
+ MotionEvent.ACTION_CANCEL -> {
98
+ dragging = false
99
+ }
100
+ }
101
+ } else {
102
+ dragging = false
103
+ }
104
+
105
+ return dragging || super.onInterceptTouchEvent(ev)
106
+ }
107
+
108
+ @SuppressLint("ClickableViewAccessibility")
109
+ override fun onTouchEvent(ev: MotionEvent): Boolean {
110
+ if (dragging) {
111
+ when (ev.action and MotionEvent.ACTION_MASK) {
112
+ MotionEvent.ACTION_UP,
113
+ MotionEvent.ACTION_CANCEL -> {
114
+ dragging = false
115
+ }
116
+ }
117
+ // Let parent CoordinatorLayout handle the touch for BottomSheetBehavior
118
+ return super.onTouchEvent(ev)
119
+ }
120
+ return super.onTouchEvent(ev)
121
+ }
122
+
123
+ private fun findScrollView(view: android.view.View): ScrollView? {
124
+ if (view is ScrollView) {
125
+ return view
126
+ }
127
+
128
+ if (view is ViewGroup) {
129
+ for (i in 0 until view.childCount) {
130
+ val scrollView = findScrollView(view.getChildAt(i))
131
+ if (scrollView != null) {
132
+ return scrollView
133
+ }
134
+ }
135
+ }
136
+
137
+ return null
138
+ }
55
139
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lodev09/react-native-true-sheet",
3
- "version": "3.6.9",
3
+ "version": "3.6.10",
4
4
  "description": "The true native bottom sheet experience for your React Native Apps.",
5
5
  "source": "./src/index.ts",
6
6
  "main": "./lib/module/index.js",