@sdcx/bottom-sheet 0.16.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 +70 -73
- 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 -401
- 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,23 +162,19 @@ public class BottomSheet extends ReactViewGroup implements NestedScrollingParent
|
|
|
162
162
|
this.draggable = draggable;
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
-
public void
|
|
166
|
-
if (this.
|
|
167
|
-
return;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
if (this.state == SETTLING) {
|
|
165
|
+
public void setStatus(BottomSheetStatus status) {
|
|
166
|
+
if (this.status == status) {
|
|
171
167
|
return;
|
|
172
168
|
}
|
|
173
169
|
|
|
174
170
|
if (contentView == null) {
|
|
175
171
|
// The view is not laid out yet; modify mState and let onLayoutChild handle it later
|
|
176
|
-
if (
|
|
177
|
-
this.
|
|
172
|
+
if (status == COLLAPSED || status == EXPANDED || status == HIDDEN) {
|
|
173
|
+
this.status = status;
|
|
178
174
|
}
|
|
179
175
|
return;
|
|
180
176
|
}
|
|
181
|
-
|
|
177
|
+
settleToStatus(contentView, status);
|
|
182
178
|
}
|
|
183
179
|
|
|
184
180
|
@Nullable
|
|
@@ -186,7 +182,7 @@ public class BottomSheet extends ReactViewGroup implements NestedScrollingParent
|
|
|
186
182
|
View findScrollingChild(View view) {
|
|
187
183
|
if (ViewCompat.isNestedScrollingEnabled(view)) {
|
|
188
184
|
if (!view.canScrollHorizontally(1) && !view.canScrollHorizontally(-1) &&
|
|
189
|
-
|
|
185
|
+
(view.canScrollVertically(-1) || view.canScrollVertically(1))) {
|
|
190
186
|
return view;
|
|
191
187
|
}
|
|
192
188
|
}
|
|
@@ -207,12 +203,13 @@ public class BottomSheet extends ReactViewGroup implements NestedScrollingParent
|
|
|
207
203
|
return null;
|
|
208
204
|
}
|
|
209
205
|
|
|
206
|
+
@NonNull
|
|
210
207
|
public PointerEvents getPointerEvents() {
|
|
211
208
|
return PointerEvents.BOX_NONE;
|
|
212
209
|
}
|
|
213
210
|
|
|
214
211
|
@Override
|
|
215
|
-
public boolean onInterceptTouchEvent(MotionEvent event) {
|
|
212
|
+
public boolean onInterceptTouchEvent(@NonNull MotionEvent event) {
|
|
216
213
|
if (shouldInterceptTouchEvent(event)) {
|
|
217
214
|
NativeGestureUtil.notifyNativeGestureStarted(this, event);
|
|
218
215
|
return true;
|
|
@@ -250,7 +247,7 @@ public class BottomSheet extends ReactViewGroup implements NestedScrollingParent
|
|
|
250
247
|
initialY = (int) event.getY();
|
|
251
248
|
// Only intercept nested scrolling events here if the view not being moved by the
|
|
252
249
|
// ViewDragHelper.
|
|
253
|
-
if (
|
|
250
|
+
if (status != SETTLING) {
|
|
254
251
|
View scroll = nestedScrollingChildRef != null ? nestedScrollingChildRef.get() : null;
|
|
255
252
|
if (scroll != null && isPointInChildBounds(scroll, initialX, initialY)) {
|
|
256
253
|
activePointerId = event.getPointerId(event.getActionIndex());
|
|
@@ -259,7 +256,7 @@ public class BottomSheet extends ReactViewGroup implements NestedScrollingParent
|
|
|
259
256
|
}
|
|
260
257
|
|
|
261
258
|
ignoreEvents = activePointerId == MotionEvent.INVALID_POINTER_ID
|
|
262
|
-
|
|
259
|
+
&& !isPointInChildBounds(contentView, initialX, initialY);
|
|
263
260
|
break;
|
|
264
261
|
default: // fall out
|
|
265
262
|
}
|
|
@@ -273,22 +270,22 @@ public class BottomSheet extends ReactViewGroup implements NestedScrollingParent
|
|
|
273
270
|
// happening over the scrolling content as nested scrolling logic handles that case.
|
|
274
271
|
View scroll = nestedScrollingChildRef != null ? nestedScrollingChildRef.get() : null;
|
|
275
272
|
return action == MotionEvent.ACTION_MOVE
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
273
|
+
&& scroll != null
|
|
274
|
+
&& !ignoreEvents
|
|
275
|
+
&& status != DRAGGING
|
|
276
|
+
&& !isPointInChildBounds(scroll, (int) event.getX(), (int) event.getY())
|
|
277
|
+
&& viewDragHelper != null
|
|
278
|
+
&& Math.abs(initialY - event.getY()) > viewDragHelper.getTouchSlop();
|
|
282
279
|
}
|
|
283
280
|
|
|
284
281
|
@Override
|
|
285
|
-
public boolean onTouchEvent(MotionEvent event) {
|
|
282
|
+
public boolean onTouchEvent(@NonNull MotionEvent event) {
|
|
286
283
|
if (!draggable) {
|
|
287
284
|
return false;
|
|
288
285
|
}
|
|
289
286
|
|
|
290
287
|
int action = event.getActionMasked();
|
|
291
|
-
if (
|
|
288
|
+
if (status == DRAGGING && action == MotionEvent.ACTION_DOWN) {
|
|
292
289
|
return true;
|
|
293
290
|
}
|
|
294
291
|
if (viewDragHelper != null) {
|
|
@@ -336,22 +333,22 @@ public class BottomSheet extends ReactViewGroup implements NestedScrollingParent
|
|
|
336
333
|
if (newTop < expandedOffset) {
|
|
337
334
|
consumed[1] = currentTop - expandedOffset;
|
|
338
335
|
ViewCompat.offsetTopAndBottom(child, -consumed[1]);
|
|
339
|
-
|
|
336
|
+
setStatusInternal(EXPANDED);
|
|
340
337
|
} else {
|
|
341
338
|
consumed[1] = dy;
|
|
342
339
|
ViewCompat.offsetTopAndBottom(child, -dy);
|
|
343
|
-
|
|
340
|
+
setStatusInternal(DRAGGING);
|
|
344
341
|
}
|
|
345
342
|
} else if (dy < 0) { // Downward
|
|
346
343
|
if (!target.canScrollVertically(-1)) {
|
|
347
344
|
if (newTop <= collapsedOffset) {
|
|
348
345
|
consumed[1] = dy;
|
|
349
346
|
ViewCompat.offsetTopAndBottom(child, -dy);
|
|
350
|
-
|
|
347
|
+
setStatusInternal(DRAGGING);
|
|
351
348
|
} else {
|
|
352
349
|
consumed[1] = currentTop - collapsedOffset;
|
|
353
350
|
ViewCompat.offsetTopAndBottom(child, -consumed[1]);
|
|
354
|
-
|
|
351
|
+
setStatusInternal(COLLAPSED);
|
|
355
352
|
}
|
|
356
353
|
}
|
|
357
354
|
}
|
|
@@ -372,7 +369,7 @@ public class BottomSheet extends ReactViewGroup implements NestedScrollingParent
|
|
|
372
369
|
View child = contentView;
|
|
373
370
|
|
|
374
371
|
if (child.getTop() == expandedOffset) {
|
|
375
|
-
|
|
372
|
+
setStatusInternal(EXPANDED);
|
|
376
373
|
return;
|
|
377
374
|
}
|
|
378
375
|
|
|
@@ -381,7 +378,7 @@ public class BottomSheet extends ReactViewGroup implements NestedScrollingParent
|
|
|
381
378
|
}
|
|
382
379
|
|
|
383
380
|
int top;
|
|
384
|
-
|
|
381
|
+
BottomSheetStatus targetState;
|
|
385
382
|
|
|
386
383
|
if (lastNestedScrollDy > 0) {
|
|
387
384
|
top = expandedOffset;
|
|
@@ -411,7 +408,7 @@ public class BottomSheet extends ReactViewGroup implements NestedScrollingParent
|
|
|
411
408
|
@Override
|
|
412
409
|
public boolean onNestedPreFling(@NonNull View target, float velocityX, float velocityY) {
|
|
413
410
|
if (nestedScrollingChildRef != null) {
|
|
414
|
-
return target == nestedScrollingChildRef.get() && (
|
|
411
|
+
return target == nestedScrollingChildRef.get() && (status != EXPANDED);
|
|
415
412
|
} else {
|
|
416
413
|
return false;
|
|
417
414
|
}
|
|
@@ -459,13 +456,13 @@ public class BottomSheet extends ReactViewGroup implements NestedScrollingParent
|
|
|
459
456
|
private final ViewDragHelper.Callback dragCallback = new ViewDragHelper.Callback() {
|
|
460
457
|
@Override
|
|
461
458
|
public boolean tryCaptureView(@NonNull View child, int pointerId) {
|
|
462
|
-
if (
|
|
459
|
+
if (status == DRAGGING) {
|
|
463
460
|
return false;
|
|
464
461
|
}
|
|
465
462
|
if (touchingScrollingChild) {
|
|
466
463
|
return false;
|
|
467
464
|
}
|
|
468
|
-
if (
|
|
465
|
+
if (status == EXPANDED && activePointerId == pointerId) {
|
|
469
466
|
View scroll = nestedScrollingChildRef != null ? nestedScrollingChildRef.get() : null;
|
|
470
467
|
if (scroll != null && scroll.canScrollVertically(-1)) {
|
|
471
468
|
// Let the content scroll up
|
|
@@ -483,14 +480,14 @@ public class BottomSheet extends ReactViewGroup implements NestedScrollingParent
|
|
|
483
480
|
@Override
|
|
484
481
|
public void onViewDragStateChanged(int state) {
|
|
485
482
|
if (state == ViewDragHelper.STATE_DRAGGING) {
|
|
486
|
-
|
|
483
|
+
setStatusInternal(DRAGGING);
|
|
487
484
|
}
|
|
488
485
|
}
|
|
489
486
|
|
|
490
487
|
@Override
|
|
491
488
|
public void onViewReleased(@NonNull View releasedChild, float xvel, float yvel) {
|
|
492
489
|
int top;
|
|
493
|
-
|
|
490
|
+
BottomSheetStatus targetState;
|
|
494
491
|
if (yvel < 0) { // Moving up
|
|
495
492
|
top = expandedOffset;
|
|
496
493
|
targetState = EXPANDED;
|
|
@@ -531,60 +528,60 @@ public class BottomSheet extends ReactViewGroup implements NestedScrollingParent
|
|
|
531
528
|
|
|
532
529
|
void dispatchOnSlide(int top) {
|
|
533
530
|
if (contentView != null) {
|
|
534
|
-
sentEvent(new
|
|
531
|
+
sentEvent(new OnSlideEvent(UIManagerHelper.getSurfaceId(reactContext), getId(), top, expandedOffset, collapsedOffset));
|
|
535
532
|
}
|
|
536
533
|
}
|
|
537
534
|
|
|
538
|
-
void
|
|
535
|
+
void settleToStatus(@NonNull View child, BottomSheetStatus status) {
|
|
539
536
|
int top;
|
|
540
|
-
if (
|
|
537
|
+
if (status == COLLAPSED) {
|
|
541
538
|
top = collapsedOffset;
|
|
542
|
-
} else if (
|
|
539
|
+
} else if (status == EXPANDED) {
|
|
543
540
|
top = expandedOffset;
|
|
544
|
-
} else if (
|
|
541
|
+
} else if (status == HIDDEN) {
|
|
545
542
|
top = getHeight();
|
|
546
543
|
} else {
|
|
547
|
-
throw new IllegalArgumentException("Illegal
|
|
544
|
+
throw new IllegalArgumentException("Illegal status argument: " + status);
|
|
548
545
|
}
|
|
549
|
-
startSettlingAnimation(child,
|
|
546
|
+
startSettlingAnimation(child, status, top, false);
|
|
550
547
|
}
|
|
551
548
|
|
|
552
|
-
void startSettlingAnimation(View child,
|
|
549
|
+
void startSettlingAnimation(View child, BottomSheetStatus status, int top, boolean settleFromViewDragHelper) {
|
|
553
550
|
boolean startedSettling =
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
551
|
+
viewDragHelper != null
|
|
552
|
+
&& (settleFromViewDragHelper
|
|
553
|
+
? viewDragHelper.settleCapturedViewAt(child.getLeft(), top)
|
|
554
|
+
: viewDragHelper.smoothSlideViewTo(child, child.getLeft(), top));
|
|
558
555
|
if (startedSettling) {
|
|
559
|
-
|
|
560
|
-
// STATE_SETTLING won't animate the material shape, so do that here with the target
|
|
561
|
-
// updateDrawableForTargetState(
|
|
556
|
+
setStatusInternal(SETTLING);
|
|
557
|
+
// STATE_SETTLING won't animate the material shape, so do that here with the target status.
|
|
558
|
+
// updateDrawableForTargetState(status);
|
|
562
559
|
if (settleRunnable == null) {
|
|
563
560
|
// If the singleton SettleRunnable instance has not been instantiated, create it.
|
|
564
|
-
settleRunnable = new SettleRunnable(child,
|
|
561
|
+
settleRunnable = new SettleRunnable(child, status);
|
|
565
562
|
}
|
|
566
|
-
// 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.
|
|
567
564
|
if (!settleRunnable.isPosted) {
|
|
568
|
-
settleRunnable.
|
|
565
|
+
settleRunnable.targetStatus = status;
|
|
569
566
|
ViewCompat.postOnAnimation(child, settleRunnable);
|
|
570
567
|
settleRunnable.isPosted = true;
|
|
571
568
|
} else {
|
|
572
|
-
// Otherwise, if it has been posted, just update the target
|
|
573
|
-
settleRunnable.
|
|
569
|
+
// Otherwise, if it has been posted, just update the target status.
|
|
570
|
+
settleRunnable.targetStatus = status;
|
|
574
571
|
}
|
|
575
572
|
} else {
|
|
576
|
-
|
|
573
|
+
setStatusInternal(status);
|
|
577
574
|
}
|
|
578
575
|
}
|
|
579
576
|
|
|
580
|
-
void
|
|
581
|
-
if (this.
|
|
577
|
+
void setStatusInternal(BottomSheetStatus status) {
|
|
578
|
+
if (this.status == status) {
|
|
582
579
|
return;
|
|
583
580
|
}
|
|
584
|
-
this.
|
|
581
|
+
this.status = status;
|
|
585
582
|
|
|
586
|
-
if (
|
|
587
|
-
sentEvent(new
|
|
583
|
+
if (status == COLLAPSED || status == EXPANDED || status == HIDDEN) {
|
|
584
|
+
sentEvent(new OnStateChangedEvent(UIManagerHelper.getSurfaceId(reactContext), getId(), status.name().toLowerCase()));
|
|
588
585
|
}
|
|
589
586
|
}
|
|
590
587
|
|
|
@@ -594,11 +591,11 @@ public class BottomSheet extends ReactViewGroup implements NestedScrollingParent
|
|
|
594
591
|
|
|
595
592
|
private boolean isPosted;
|
|
596
593
|
|
|
597
|
-
|
|
594
|
+
BottomSheetStatus targetStatus;
|
|
598
595
|
|
|
599
|
-
SettleRunnable(View view,
|
|
596
|
+
SettleRunnable(View view, BottomSheetStatus targetStatus) {
|
|
600
597
|
this.view = view;
|
|
601
|
-
this.
|
|
598
|
+
this.targetStatus = targetStatus;
|
|
602
599
|
}
|
|
603
600
|
|
|
604
601
|
@Override
|
|
@@ -606,7 +603,7 @@ public class BottomSheet extends ReactViewGroup implements NestedScrollingParent
|
|
|
606
603
|
if (viewDragHelper != null && viewDragHelper.continueSettling(true)) {
|
|
607
604
|
ViewCompat.postOnAnimation(view, this);
|
|
608
605
|
} else {
|
|
609
|
-
|
|
606
|
+
setStatusInternal(targetStatus);
|
|
610
607
|
}
|
|
611
608
|
this.isPosted = false;
|
|
612
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);
|