@sdcx/bottom-sheet 0.17.0 → 1.0.0
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.
- package/README.md +57 -51
- package/RNBottomSheet.podspec +5 -4
- package/android/build.gradle +42 -19
- package/android/src/main/java/com/reactnative/bottomsheet/BottomSheet.java +59 -58
- package/android/src/main/java/com/reactnative/bottomsheet/BottomSheetManager.java +12 -6
- package/android/src/main/java/com/reactnative/bottomsheet/{BottomSheetState.java → BottomSheetStatus.java} +1 -1
- package/android/src/main/java/com/reactnative/bottomsheet/{OffsetChangedEvent.java → OnSlideEvent.java} +5 -3
- package/android/src/main/java/com/reactnative/bottomsheet/{StateChangedEvent.java → OnStateChangedEvent.java} +5 -3
- package/dist/BottomSheetNativeComponent.d.ts +20 -0
- package/dist/BottomSheetNativeComponent.js +2 -0
- package/dist/index.d.ts +8 -15
- package/dist/index.js +9 -9
- package/ios/BottomSheet/{RNBottomSheetOffsetChangedEvent.m → Event/RNBottomSheetOffsetChangedEvent.mm} +3 -1
- package/ios/BottomSheet/{RNBottomSheetStateChangedEvent.h → Event/RNBottomSheetStateChangedEvent.h} +1 -3
- package/ios/BottomSheet/{RNBottomSheetStateChangedEvent.m → Event/RNBottomSheetStateChangedEvent.mm} +4 -4
- package/ios/BottomSheet/RNBottomSheetComponentView.h +10 -0
- package/ios/BottomSheet/RNBottomSheetComponentView.mm +555 -0
- package/package.json +50 -38
- package/src/BottomSheetNativeComponent.ts +26 -0
- package/src/index.tsx +51 -70
- package/docs/assets/pagerview.gif +0 -0
- package/docs/assets/scrollview.gif +0 -0
- package/docs/assets/struct.png +0 -0
- package/ios/BottomSheet/RNBottomSheet.h +0 -21
- package/ios/BottomSheet/RNBottomSheet.m +0 -407
- package/ios/BottomSheet/RNBottomSheetManager.h +0 -9
- package/ios/BottomSheet/RNBottomSheetManager.m +0 -24
- package/ios/BottomSheet/RNBottomSheetState.h +0 -17
- package/ios/BottomSheet/RNBottomSheetState.m +0 -38
- /package/ios/BottomSheet/{RNBottomSheetOffsetChangedEvent.h → Event/RNBottomSheetOffsetChangedEvent.h} +0 -0
package/README.md
CHANGED
|
@@ -4,9 +4,15 @@
|
|
|
4
4
|
|
|
5
5
|
它位于屏幕底部,可拖拽,支持嵌套滚动,可以和可滚动视图(`FlatList`, `FlashList`, `WebView` 等等)一起使用。
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
<img src="https://raw.githubusercontent.com/sdcxtech/react-native-troika/master/packages/bottom-sheet/docs/assets/scrollview.gif" width="320">
|
|
8
|
+
<img src="https://raw.githubusercontent.com/sdcxtech/react-native-troika/master/packages/bottom-sheet/docs/assets/pagerview.gif" width="320">
|
|
9
|
+
|
|
10
|
+
## 版本兼容
|
|
11
|
+
|
|
12
|
+
| 版本 | RN 版本 | RN 架构 |
|
|
13
|
+
| ---- | ------- | ------- |
|
|
14
|
+
| 0.x | < 0.82 | 旧架构 |
|
|
15
|
+
| 1.x | >= 0.82 | 新架构 |
|
|
10
16
|
|
|
11
17
|
## Installation
|
|
12
18
|
|
|
@@ -21,26 +27,26 @@ pod install
|
|
|
21
27
|
`BottomSheet` 在使用上是非常简单的,几乎没有什么心智负担。
|
|
22
28
|
|
|
23
29
|
```tsx
|
|
24
|
-
import BottomSheet from '@sdcx/bottom-sheet'
|
|
30
|
+
import BottomSheet from '@sdcx/bottom-sheet';
|
|
25
31
|
|
|
26
32
|
const App = () => {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
33
|
+
return (
|
|
34
|
+
<View style={styles.container}>
|
|
35
|
+
<ScrollView>...</ScrollView>
|
|
36
|
+
<BottomSheet peeekHeight={200}>
|
|
37
|
+
{
|
|
38
|
+
// 在这里放置你的内容,可以是任何组件,如:
|
|
39
|
+
}
|
|
40
|
+
<View />
|
|
41
|
+
<PagerView>
|
|
42
|
+
<FlatList nestedScrollEnabled />
|
|
43
|
+
<ScrollView nestedScrollEnabled />
|
|
44
|
+
<WebView />
|
|
45
|
+
</PagerView>
|
|
46
|
+
</BottomSheet>
|
|
47
|
+
</View>
|
|
48
|
+
);
|
|
49
|
+
};
|
|
44
50
|
```
|
|
45
51
|
|
|
46
52
|
> :exclamation: :exclamation: :exclamation:
|
|
@@ -54,53 +60,53 @@ const App = () => {
|
|
|
54
60
|
|
|
55
61
|
`BottomSheet` 由内外两层视图组成,外层是绝对定位,默认填满父组件,除非设置了 `top` 样式属性,内层也是绝对定位,默认填满外层视图。外层的位置固定不变,内层则可拖动。
|
|
56
62
|
|
|
57
|
-

|
|
58
64
|
|
|
59
65
|
`BottomSheet` 拥有 3 个属性和两个回调。
|
|
60
66
|
|
|
61
67
|
### 属性
|
|
62
68
|
|
|
63
|
-
-
|
|
69
|
+
- `peekHeight`, 是指 BottomSheet 收起时,在屏幕上露出的高度,默认是 200。
|
|
64
70
|
|
|
65
|
-
-
|
|
71
|
+
- `state`, 是指 BottomSheet 的状态,有三种状态:
|
|
66
72
|
|
|
67
|
-
|
|
73
|
+
- `'collapsed'`,收起状态,此时 BottomSheet 的高度为 `peekHeight`。
|
|
68
74
|
|
|
69
|
-
|
|
75
|
+
- `'expanded'`,展开状态,此时 BottomSheet 的高度为父组件的高度或内容的高度,参考 `fitToContents` 属性。
|
|
70
76
|
|
|
71
|
-
|
|
77
|
+
- `'hidden'`,隐藏状态,此时 BottomSheet 的高度为 0。
|
|
72
78
|
|
|
73
|
-
-
|
|
79
|
+
- `fitToContents`,是指 BottomSheet 在展开时,是否适应内容的高度,默认是 `false`。当和可滚动列表,譬如 ScrollView 一起使用时,请保持默认值。
|
|
74
80
|
|
|
75
|
-
-
|
|
81
|
+
- `contentContainerStyle`,用来设置内层视图的样式。
|
|
76
82
|
|
|
77
83
|
### 回调
|
|
78
84
|
|
|
79
|
-
-
|
|
85
|
+
- `onStateChanged`, 是指 BottomSheet 状态变化时的回调,它和 `state` 属性是一对,用来实现受控模式。
|
|
80
86
|
|
|
81
|
-
|
|
82
|
-
|
|
87
|
+
```tsx
|
|
88
|
+
export type BottomSheetState = 'collapsed' | 'expanded' | 'hidden';
|
|
83
89
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
90
|
+
export interface StateChangedEventData {
|
|
91
|
+
state: BottomSheetState;
|
|
92
|
+
}
|
|
87
93
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
94
|
+
interface NativeBottomSheetProps extends ViewProps {
|
|
95
|
+
onStateChanged?: (event: NativeSyntheticEvent<StateChangedEventData>) => void;
|
|
96
|
+
}
|
|
97
|
+
```
|
|
92
98
|
|
|
93
|
-
-
|
|
99
|
+
- `onSlide`, 是指 BottomSheet 滑动时的回调,可以用它来实现一些动画效果。
|
|
94
100
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
101
|
+
```tsx
|
|
102
|
+
export interface OffsetChangedEventData {
|
|
103
|
+
progress: number; // 是指 `BottomSheet` 当前的位置在 `collapsedOffset` 和 `expandedOffset` 之间的比例,它的值在 0 和 1 之间。
|
|
104
|
+
offset: number; // 是指 `BottomSheet` 当前的位置,它的值在 `collapsedOffset` 和 `expandedOffset` 之间。
|
|
105
|
+
expandedOffset: number; // 是指 `BottomSheet` 完全展开时,内层顶部距离外层顶部的距离,通常是 0。但如果设置了 `fitToContents` 属性,则可能大于 0。
|
|
106
|
+
collapsedOffset: number; // 是指 `BottomSheet` 完全收起时,内层顶部距离外层顶部的距离。可以看到,它的值等于外层的高度减去 `peekHeight`。
|
|
107
|
+
}
|
|
102
108
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
109
|
+
interface NativeBottomSheetProps extends ViewProps {
|
|
110
|
+
onSlide?: (event: NativeSyntheticEvent<OffsetChangedEventData>) => void;
|
|
111
|
+
}
|
|
112
|
+
```
|
package/RNBottomSheet.podspec
CHANGED
|
@@ -6,13 +6,14 @@ Pod::Spec.new do |s|
|
|
|
6
6
|
s.name = "RNBottomSheet"
|
|
7
7
|
s.version = package["version"]
|
|
8
8
|
s.summary = package["description"]
|
|
9
|
-
|
|
9
|
+
|
|
10
10
|
s.homepage = package["homepage"]
|
|
11
11
|
s.license = package["license"]
|
|
12
12
|
s.authors = package["author"]
|
|
13
|
-
s.platforms = { :ios =>
|
|
13
|
+
s.platforms = { :ios => min_ios_version_supported }
|
|
14
14
|
s.source = { :git => "https://github.com/github-account/bottom-sheet.git", :tag => "#{s.version}" }
|
|
15
15
|
|
|
16
16
|
s.source_files = "ios/BottomSheet/**/*.{h,m,mm}"
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
|
|
18
|
+
install_modules_dependencies(s)
|
|
19
|
+
end
|
package/android/build.gradle
CHANGED
|
@@ -1,35 +1,58 @@
|
|
|
1
|
-
// android/build.gradle
|
|
2
1
|
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
buildscript {
|
|
3
|
+
repositories {
|
|
4
|
+
mavenCentral()
|
|
5
|
+
google()
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
dependencies {
|
|
9
|
+
classpath "com.android.tools.build:gradle:8.7.2"
|
|
10
|
+
}
|
|
5
11
|
}
|
|
6
12
|
|
|
7
13
|
apply plugin: 'com.android.library'
|
|
14
|
+
apply plugin: 'com.facebook.react'
|
|
15
|
+
|
|
16
|
+
def safeExtGet(prop, fallback) {
|
|
17
|
+
rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
|
|
18
|
+
}
|
|
8
19
|
|
|
9
20
|
android {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
21
|
+
|
|
22
|
+
def agpVersion = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')
|
|
23
|
+
// Check AGP version for backward compatibility w/react-native versions still on gradle plugin 6
|
|
24
|
+
def major = agpVersion[0].toInteger()
|
|
25
|
+
def minor = agpVersion[1].toInteger()
|
|
26
|
+
if ((major == 7 && minor >= 3) || major >= 8) {
|
|
27
|
+
namespace "com.reactnative.bottomsheet"
|
|
28
|
+
buildFeatures {
|
|
29
|
+
buildConfig true
|
|
13
30
|
}
|
|
31
|
+
}
|
|
14
32
|
|
|
15
|
-
|
|
16
|
-
|
|
33
|
+
compileSdkVersion safeExtGet('compileSdkVersion', 35)
|
|
34
|
+
buildToolsVersion safeExtGet('buildToolsVersion', '35.0.0')
|
|
17
35
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
versionName "1.0.0"
|
|
23
|
-
}
|
|
36
|
+
defaultConfig {
|
|
37
|
+
minSdkVersion safeExtGet('minSdkVersion', 24)
|
|
38
|
+
targetSdkVersion safeExtGet('targetSdkVersion', 35)
|
|
39
|
+
}
|
|
24
40
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
41
|
+
sourceSets {
|
|
42
|
+
main {
|
|
43
|
+
java.srcDirs += [
|
|
44
|
+
"generated/java",
|
|
45
|
+
"generated/jni"
|
|
46
|
+
]
|
|
28
47
|
}
|
|
29
48
|
}
|
|
30
49
|
}
|
|
31
50
|
|
|
51
|
+
repositories {
|
|
52
|
+
google()
|
|
53
|
+
mavenCentral()
|
|
54
|
+
}
|
|
55
|
+
|
|
32
56
|
dependencies {
|
|
33
|
-
|
|
34
|
-
implementation 'com.facebook.react:react-native:+'
|
|
57
|
+
api 'com.facebook.react:react-native:+'
|
|
35
58
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
package com.reactnative.bottomsheet;
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
import static com.reactnative.bottomsheet.
|
|
5
|
-
import static com.reactnative.bottomsheet.
|
|
6
|
-
import static com.reactnative.bottomsheet.
|
|
7
|
-
import static com.reactnative.bottomsheet.
|
|
8
|
-
import static com.reactnative.bottomsheet.
|
|
4
|
+
import static com.reactnative.bottomsheet.BottomSheetStatus.COLLAPSED;
|
|
5
|
+
import static com.reactnative.bottomsheet.BottomSheetStatus.DRAGGING;
|
|
6
|
+
import static com.reactnative.bottomsheet.BottomSheetStatus.EXPANDED;
|
|
7
|
+
import static com.reactnative.bottomsheet.BottomSheetStatus.HIDDEN;
|
|
8
|
+
import static com.reactnative.bottomsheet.BottomSheetStatus.SETTLING;
|
|
9
9
|
import static java.lang.Math.max;
|
|
10
10
|
|
|
11
11
|
import android.annotation.SuppressLint;
|
|
@@ -51,7 +51,7 @@ public class BottomSheet extends ReactViewGroup implements NestedScrollingParent
|
|
|
51
51
|
this.nestedScrollingParentHelper = new NestedScrollingParentHelper(this);
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
private
|
|
54
|
+
private BottomSheetStatus status = COLLAPSED;
|
|
55
55
|
|
|
56
56
|
private SettleRunnable settleRunnable = null;
|
|
57
57
|
|
|
@@ -114,11 +114,11 @@ public class BottomSheet extends ReactViewGroup implements NestedScrollingParent
|
|
|
114
114
|
|
|
115
115
|
getViewTreeObserver().removeOnPreDrawListener(preDrawListener);
|
|
116
116
|
int top = contentView.getTop();
|
|
117
|
-
if (
|
|
117
|
+
if (status == COLLAPSED) {
|
|
118
118
|
child.offsetTopAndBottom(collapsedOffset - top);
|
|
119
|
-
} else if (
|
|
119
|
+
} else if (status == EXPANDED) {
|
|
120
120
|
child.offsetTopAndBottom(expandedOffset - top);
|
|
121
|
-
} else if (
|
|
121
|
+
} else if (status == HIDDEN) {
|
|
122
122
|
child.offsetTopAndBottom(getHeight() - top);
|
|
123
123
|
}
|
|
124
124
|
getViewTreeObserver().addOnPreDrawListener(preDrawListener);
|
|
@@ -152,8 +152,8 @@ public class BottomSheet extends ReactViewGroup implements NestedScrollingParent
|
|
|
152
152
|
this.peekHeight = max(peekHeight, 0);
|
|
153
153
|
if (contentView != null) {
|
|
154
154
|
calculateOffset();
|
|
155
|
-
if (
|
|
156
|
-
|
|
155
|
+
if (status == COLLAPSED) {
|
|
156
|
+
settleToStatus(contentView, status);
|
|
157
157
|
}
|
|
158
158
|
}
|
|
159
159
|
}
|
|
@@ -162,19 +162,19 @@ public class BottomSheet extends ReactViewGroup implements NestedScrollingParent
|
|
|
162
162
|
this.draggable = draggable;
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
-
public void
|
|
166
|
-
if (this.
|
|
165
|
+
public void setStatus(BottomSheetStatus status) {
|
|
166
|
+
if (this.status == status) {
|
|
167
167
|
return;
|
|
168
168
|
}
|
|
169
169
|
|
|
170
170
|
if (contentView == null) {
|
|
171
171
|
// The view is not laid out yet; modify mState and let onLayoutChild handle it later
|
|
172
|
-
if (
|
|
173
|
-
this.
|
|
172
|
+
if (status == COLLAPSED || status == EXPANDED || status == HIDDEN) {
|
|
173
|
+
this.status = status;
|
|
174
174
|
}
|
|
175
175
|
return;
|
|
176
176
|
}
|
|
177
|
-
|
|
177
|
+
settleToStatus(contentView, status);
|
|
178
178
|
}
|
|
179
179
|
|
|
180
180
|
@Nullable
|
|
@@ -203,12 +203,13 @@ public class BottomSheet extends ReactViewGroup implements NestedScrollingParent
|
|
|
203
203
|
return null;
|
|
204
204
|
}
|
|
205
205
|
|
|
206
|
+
@NonNull
|
|
206
207
|
public PointerEvents getPointerEvents() {
|
|
207
208
|
return PointerEvents.BOX_NONE;
|
|
208
209
|
}
|
|
209
210
|
|
|
210
211
|
@Override
|
|
211
|
-
public boolean onInterceptTouchEvent(MotionEvent event) {
|
|
212
|
+
public boolean onInterceptTouchEvent(@NonNull MotionEvent event) {
|
|
212
213
|
if (shouldInterceptTouchEvent(event)) {
|
|
213
214
|
NativeGestureUtil.notifyNativeGestureStarted(this, event);
|
|
214
215
|
return true;
|
|
@@ -246,7 +247,7 @@ public class BottomSheet extends ReactViewGroup implements NestedScrollingParent
|
|
|
246
247
|
initialY = (int) event.getY();
|
|
247
248
|
// Only intercept nested scrolling events here if the view not being moved by the
|
|
248
249
|
// ViewDragHelper.
|
|
249
|
-
if (
|
|
250
|
+
if (status != SETTLING) {
|
|
250
251
|
View scroll = nestedScrollingChildRef != null ? nestedScrollingChildRef.get() : null;
|
|
251
252
|
if (scroll != null && isPointInChildBounds(scroll, initialX, initialY)) {
|
|
252
253
|
activePointerId = event.getPointerId(event.getActionIndex());
|
|
@@ -271,20 +272,20 @@ public class BottomSheet extends ReactViewGroup implements NestedScrollingParent
|
|
|
271
272
|
return action == MotionEvent.ACTION_MOVE
|
|
272
273
|
&& scroll != null
|
|
273
274
|
&& !ignoreEvents
|
|
274
|
-
&&
|
|
275
|
+
&& status != DRAGGING
|
|
275
276
|
&& !isPointInChildBounds(scroll, (int) event.getX(), (int) event.getY())
|
|
276
277
|
&& viewDragHelper != null
|
|
277
278
|
&& Math.abs(initialY - event.getY()) > viewDragHelper.getTouchSlop();
|
|
278
279
|
}
|
|
279
280
|
|
|
280
281
|
@Override
|
|
281
|
-
public boolean onTouchEvent(MotionEvent event) {
|
|
282
|
+
public boolean onTouchEvent(@NonNull MotionEvent event) {
|
|
282
283
|
if (!draggable) {
|
|
283
284
|
return false;
|
|
284
285
|
}
|
|
285
286
|
|
|
286
287
|
int action = event.getActionMasked();
|
|
287
|
-
if (
|
|
288
|
+
if (status == DRAGGING && action == MotionEvent.ACTION_DOWN) {
|
|
288
289
|
return true;
|
|
289
290
|
}
|
|
290
291
|
if (viewDragHelper != null) {
|
|
@@ -332,22 +333,22 @@ public class BottomSheet extends ReactViewGroup implements NestedScrollingParent
|
|
|
332
333
|
if (newTop < expandedOffset) {
|
|
333
334
|
consumed[1] = currentTop - expandedOffset;
|
|
334
335
|
ViewCompat.offsetTopAndBottom(child, -consumed[1]);
|
|
335
|
-
|
|
336
|
+
setStatusInternal(EXPANDED);
|
|
336
337
|
} else {
|
|
337
338
|
consumed[1] = dy;
|
|
338
339
|
ViewCompat.offsetTopAndBottom(child, -dy);
|
|
339
|
-
|
|
340
|
+
setStatusInternal(DRAGGING);
|
|
340
341
|
}
|
|
341
342
|
} else if (dy < 0) { // Downward
|
|
342
343
|
if (!target.canScrollVertically(-1)) {
|
|
343
344
|
if (newTop <= collapsedOffset) {
|
|
344
345
|
consumed[1] = dy;
|
|
345
346
|
ViewCompat.offsetTopAndBottom(child, -dy);
|
|
346
|
-
|
|
347
|
+
setStatusInternal(DRAGGING);
|
|
347
348
|
} else {
|
|
348
349
|
consumed[1] = currentTop - collapsedOffset;
|
|
349
350
|
ViewCompat.offsetTopAndBottom(child, -consumed[1]);
|
|
350
|
-
|
|
351
|
+
setStatusInternal(COLLAPSED);
|
|
351
352
|
}
|
|
352
353
|
}
|
|
353
354
|
}
|
|
@@ -368,7 +369,7 @@ public class BottomSheet extends ReactViewGroup implements NestedScrollingParent
|
|
|
368
369
|
View child = contentView;
|
|
369
370
|
|
|
370
371
|
if (child.getTop() == expandedOffset) {
|
|
371
|
-
|
|
372
|
+
setStatusInternal(EXPANDED);
|
|
372
373
|
return;
|
|
373
374
|
}
|
|
374
375
|
|
|
@@ -377,7 +378,7 @@ public class BottomSheet extends ReactViewGroup implements NestedScrollingParent
|
|
|
377
378
|
}
|
|
378
379
|
|
|
379
380
|
int top;
|
|
380
|
-
|
|
381
|
+
BottomSheetStatus targetState;
|
|
381
382
|
|
|
382
383
|
if (lastNestedScrollDy > 0) {
|
|
383
384
|
top = expandedOffset;
|
|
@@ -407,7 +408,7 @@ public class BottomSheet extends ReactViewGroup implements NestedScrollingParent
|
|
|
407
408
|
@Override
|
|
408
409
|
public boolean onNestedPreFling(@NonNull View target, float velocityX, float velocityY) {
|
|
409
410
|
if (nestedScrollingChildRef != null) {
|
|
410
|
-
return target == nestedScrollingChildRef.get() && (
|
|
411
|
+
return target == nestedScrollingChildRef.get() && (status != EXPANDED);
|
|
411
412
|
} else {
|
|
412
413
|
return false;
|
|
413
414
|
}
|
|
@@ -455,13 +456,13 @@ public class BottomSheet extends ReactViewGroup implements NestedScrollingParent
|
|
|
455
456
|
private final ViewDragHelper.Callback dragCallback = new ViewDragHelper.Callback() {
|
|
456
457
|
@Override
|
|
457
458
|
public boolean tryCaptureView(@NonNull View child, int pointerId) {
|
|
458
|
-
if (
|
|
459
|
+
if (status == DRAGGING) {
|
|
459
460
|
return false;
|
|
460
461
|
}
|
|
461
462
|
if (touchingScrollingChild) {
|
|
462
463
|
return false;
|
|
463
464
|
}
|
|
464
|
-
if (
|
|
465
|
+
if (status == EXPANDED && activePointerId == pointerId) {
|
|
465
466
|
View scroll = nestedScrollingChildRef != null ? nestedScrollingChildRef.get() : null;
|
|
466
467
|
if (scroll != null && scroll.canScrollVertically(-1)) {
|
|
467
468
|
// Let the content scroll up
|
|
@@ -479,14 +480,14 @@ public class BottomSheet extends ReactViewGroup implements NestedScrollingParent
|
|
|
479
480
|
@Override
|
|
480
481
|
public void onViewDragStateChanged(int state) {
|
|
481
482
|
if (state == ViewDragHelper.STATE_DRAGGING) {
|
|
482
|
-
|
|
483
|
+
setStatusInternal(DRAGGING);
|
|
483
484
|
}
|
|
484
485
|
}
|
|
485
486
|
|
|
486
487
|
@Override
|
|
487
488
|
public void onViewReleased(@NonNull View releasedChild, float xvel, float yvel) {
|
|
488
489
|
int top;
|
|
489
|
-
|
|
490
|
+
BottomSheetStatus targetState;
|
|
490
491
|
if (yvel < 0) { // Moving up
|
|
491
492
|
top = expandedOffset;
|
|
492
493
|
targetState = EXPANDED;
|
|
@@ -527,60 +528,60 @@ public class BottomSheet extends ReactViewGroup implements NestedScrollingParent
|
|
|
527
528
|
|
|
528
529
|
void dispatchOnSlide(int top) {
|
|
529
530
|
if (contentView != null) {
|
|
530
|
-
sentEvent(new
|
|
531
|
+
sentEvent(new OnSlideEvent(UIManagerHelper.getSurfaceId(reactContext), getId(), top, expandedOffset, collapsedOffset));
|
|
531
532
|
}
|
|
532
533
|
}
|
|
533
534
|
|
|
534
|
-
void
|
|
535
|
+
void settleToStatus(@NonNull View child, BottomSheetStatus status) {
|
|
535
536
|
int top;
|
|
536
|
-
if (
|
|
537
|
+
if (status == COLLAPSED) {
|
|
537
538
|
top = collapsedOffset;
|
|
538
|
-
} else if (
|
|
539
|
+
} else if (status == EXPANDED) {
|
|
539
540
|
top = expandedOffset;
|
|
540
|
-
} else if (
|
|
541
|
+
} else if (status == HIDDEN) {
|
|
541
542
|
top = getHeight();
|
|
542
543
|
} else {
|
|
543
|
-
throw new IllegalArgumentException("Illegal
|
|
544
|
+
throw new IllegalArgumentException("Illegal status argument: " + status);
|
|
544
545
|
}
|
|
545
|
-
startSettlingAnimation(child,
|
|
546
|
+
startSettlingAnimation(child, status, top, false);
|
|
546
547
|
}
|
|
547
548
|
|
|
548
|
-
void startSettlingAnimation(View child,
|
|
549
|
+
void startSettlingAnimation(View child, BottomSheetStatus status, int top, boolean settleFromViewDragHelper) {
|
|
549
550
|
boolean startedSettling =
|
|
550
551
|
viewDragHelper != null
|
|
551
552
|
&& (settleFromViewDragHelper
|
|
552
553
|
? viewDragHelper.settleCapturedViewAt(child.getLeft(), top)
|
|
553
554
|
: viewDragHelper.smoothSlideViewTo(child, child.getLeft(), top));
|
|
554
555
|
if (startedSettling) {
|
|
555
|
-
|
|
556
|
-
// STATE_SETTLING won't animate the material shape, so do that here with the target
|
|
557
|
-
// updateDrawableForTargetState(
|
|
556
|
+
setStatusInternal(SETTLING);
|
|
557
|
+
// STATE_SETTLING won't animate the material shape, so do that here with the target status.
|
|
558
|
+
// updateDrawableForTargetState(status);
|
|
558
559
|
if (settleRunnable == null) {
|
|
559
560
|
// If the singleton SettleRunnable instance has not been instantiated, create it.
|
|
560
|
-
settleRunnable = new SettleRunnable(child,
|
|
561
|
+
settleRunnable = new SettleRunnable(child, status);
|
|
561
562
|
}
|
|
562
|
-
// If the SettleRunnable has not been posted, post it with the correct
|
|
563
|
+
// If the SettleRunnable has not been posted, post it with the correct status.
|
|
563
564
|
if (!settleRunnable.isPosted) {
|
|
564
|
-
settleRunnable.
|
|
565
|
+
settleRunnable.targetStatus = status;
|
|
565
566
|
ViewCompat.postOnAnimation(child, settleRunnable);
|
|
566
567
|
settleRunnable.isPosted = true;
|
|
567
568
|
} else {
|
|
568
|
-
// Otherwise, if it has been posted, just update the target
|
|
569
|
-
settleRunnable.
|
|
569
|
+
// Otherwise, if it has been posted, just update the target status.
|
|
570
|
+
settleRunnable.targetStatus = status;
|
|
570
571
|
}
|
|
571
572
|
} else {
|
|
572
|
-
|
|
573
|
+
setStatusInternal(status);
|
|
573
574
|
}
|
|
574
575
|
}
|
|
575
576
|
|
|
576
|
-
void
|
|
577
|
-
if (this.
|
|
577
|
+
void setStatusInternal(BottomSheetStatus status) {
|
|
578
|
+
if (this.status == status) {
|
|
578
579
|
return;
|
|
579
580
|
}
|
|
580
|
-
this.
|
|
581
|
+
this.status = status;
|
|
581
582
|
|
|
582
|
-
if (
|
|
583
|
-
sentEvent(new
|
|
583
|
+
if (status == COLLAPSED || status == EXPANDED || status == HIDDEN) {
|
|
584
|
+
sentEvent(new OnStateChangedEvent(UIManagerHelper.getSurfaceId(reactContext), getId(), status.name().toLowerCase()));
|
|
584
585
|
}
|
|
585
586
|
}
|
|
586
587
|
|
|
@@ -590,11 +591,11 @@ public class BottomSheet extends ReactViewGroup implements NestedScrollingParent
|
|
|
590
591
|
|
|
591
592
|
private boolean isPosted;
|
|
592
593
|
|
|
593
|
-
|
|
594
|
+
BottomSheetStatus targetStatus;
|
|
594
595
|
|
|
595
|
-
SettleRunnable(View view,
|
|
596
|
+
SettleRunnable(View view, BottomSheetStatus targetStatus) {
|
|
596
597
|
this.view = view;
|
|
597
|
-
this.
|
|
598
|
+
this.targetStatus = targetStatus;
|
|
598
599
|
}
|
|
599
600
|
|
|
600
601
|
@Override
|
|
@@ -602,7 +603,7 @@ public class BottomSheet extends ReactViewGroup implements NestedScrollingParent
|
|
|
602
603
|
if (viewDragHelper != null && viewDragHelper.continueSettling(true)) {
|
|
603
604
|
ViewCompat.postOnAnimation(view, this);
|
|
604
605
|
} else {
|
|
605
|
-
|
|
606
|
+
setStatusInternal(targetStatus);
|
|
606
607
|
}
|
|
607
608
|
this.isPosted = false;
|
|
608
609
|
}
|
|
@@ -7,10 +7,12 @@ import com.facebook.react.uimanager.PixelUtil;
|
|
|
7
7
|
import com.facebook.react.uimanager.ThemedReactContext;
|
|
8
8
|
import com.facebook.react.uimanager.ViewGroupManager;
|
|
9
9
|
import com.facebook.react.uimanager.annotations.ReactProp;
|
|
10
|
+
import com.facebook.react.viewmanagers.BottomSheetManagerInterface;
|
|
10
11
|
|
|
11
12
|
import java.util.Map;
|
|
12
13
|
|
|
13
|
-
public class BottomSheetManager extends ViewGroupManager<BottomSheet>
|
|
14
|
+
public class BottomSheetManager extends ViewGroupManager<BottomSheet>
|
|
15
|
+
implements BottomSheetManagerInterface<BottomSheet> {
|
|
14
16
|
|
|
15
17
|
@NonNull
|
|
16
18
|
@Override
|
|
@@ -27,21 +29,25 @@ public class BottomSheetManager extends ViewGroupManager<BottomSheet> {
|
|
|
27
29
|
@Override
|
|
28
30
|
public Map<String, Object> getExportedCustomDirectEventTypeConstants() {
|
|
29
31
|
return MapBuilder.<String, Object>builder()
|
|
30
|
-
.put(
|
|
31
|
-
.put(
|
|
32
|
+
.put(OnStateChangedEvent.Name, MapBuilder.of("registrationName", OnStateChangedEvent.JSEventName))
|
|
33
|
+
.put(OnSlideEvent.Name, MapBuilder.of("registrationName", OnSlideEvent.JSEventName))
|
|
32
34
|
.build();
|
|
33
35
|
}
|
|
34
36
|
|
|
37
|
+
@Override
|
|
35
38
|
@ReactProp(name = "peekHeight", defaultInt = 200)
|
|
36
39
|
public void setPeekHeight(BottomSheet view, int dp) {
|
|
37
40
|
view.setPeekHeight((int) (PixelUtil.toPixelFromDIP(dp) + 0.5));
|
|
38
41
|
}
|
|
39
42
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
+
@Override
|
|
44
|
+
@ReactProp(name = "status")
|
|
45
|
+
public void setStatus(BottomSheet view, String status) {
|
|
46
|
+
assert status != null;
|
|
47
|
+
view.setStatus(BottomSheetStatus.valueOf(status.toUpperCase()));
|
|
43
48
|
}
|
|
44
49
|
|
|
50
|
+
@Override
|
|
45
51
|
@ReactProp(name = "draggable")
|
|
46
52
|
public void setDraggable(BottomSheet view, boolean draggable) {
|
|
47
53
|
view.setDraggable(draggable);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
package com.reactnative.bottomsheet;
|
|
2
2
|
|
|
3
|
+
import androidx.annotation.NonNull;
|
|
3
4
|
import androidx.annotation.Nullable;
|
|
4
5
|
|
|
5
6
|
import com.facebook.react.bridge.Arguments;
|
|
@@ -7,21 +8,22 @@ import com.facebook.react.bridge.WritableMap;
|
|
|
7
8
|
import com.facebook.react.uimanager.PixelUtil;
|
|
8
9
|
import com.facebook.react.uimanager.events.Event;
|
|
9
10
|
|
|
10
|
-
public class
|
|
11
|
-
public static final String Name = "
|
|
11
|
+
public class OnSlideEvent extends Event<OnSlideEvent> {
|
|
12
|
+
public static final String Name = "topSlide";
|
|
12
13
|
public static final String JSEventName = "onSlide";
|
|
13
14
|
|
|
14
15
|
private final int offset;
|
|
15
16
|
private final int minOffset;
|
|
16
17
|
private final int maxOffset;
|
|
17
18
|
|
|
18
|
-
public
|
|
19
|
+
public OnSlideEvent(int surfaceId, int viewTag, int offset, int minOffset, int maxOffset) {
|
|
19
20
|
super(surfaceId, viewTag);
|
|
20
21
|
this.offset = offset;
|
|
21
22
|
this.maxOffset = maxOffset;
|
|
22
23
|
this.minOffset = minOffset;
|
|
23
24
|
}
|
|
24
25
|
|
|
26
|
+
@NonNull
|
|
25
27
|
@Override
|
|
26
28
|
public String getEventName() {
|
|
27
29
|
return Name;
|