@lodev09/react-native-true-sheet 0.9.7 → 0.9.9
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 +120 -18
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetDialog.kt +199 -29
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetView.kt +44 -48
- package/android/src/main/java/com/lodev09/truesheet/core/{RootViewGroup.kt → RootSheetView.kt} +3 -8
- package/ios/TrueSheetView.swift +0 -3
- package/lib/commonjs/TrueSheet.js +59 -25
- package/lib/commonjs/TrueSheet.js.map +1 -1
- package/lib/commonjs/TrueSheetFooter.js +20 -0
- package/lib/commonjs/TrueSheetFooter.js.map +1 -0
- package/lib/commonjs/__mocks__/index.js +3 -0
- package/lib/commonjs/__mocks__/index.js.map +1 -1
- package/lib/module/TrueSheet.js +58 -24
- package/lib/module/TrueSheet.js.map +1 -1
- package/lib/module/TrueSheetFooter.js +12 -0
- package/lib/module/TrueSheetFooter.js.map +1 -0
- package/lib/module/__mocks__/index.js +3 -0
- package/lib/module/__mocks__/index.js.map +1 -1
- package/lib/typescript/src/TrueSheet.d.ts +23 -3
- package/lib/typescript/src/TrueSheet.d.ts.map +1 -1
- package/lib/typescript/src/TrueSheetFooter.d.ts +8 -0
- package/lib/typescript/src/TrueSheetFooter.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +15 -0
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/TrueSheet.tsx +74 -37
- package/src/TrueSheetFooter.tsx +18 -0
- package/src/__mocks__/index.js +4 -0
- package/src/types.ts +15 -0
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetBehavior.kt +0 -230
package/README.md
CHANGED
|
@@ -16,8 +16,7 @@ The true native bottom sheet 💩
|
|
|
16
16
|
* ✅ Handles your _Footer_ needs, natively.
|
|
17
17
|
* ✅ Handles your _Keyboard_ needs, natively.
|
|
18
18
|
* ✅ Asynchronus `ref` [methods](#methods).
|
|
19
|
-
* ✅
|
|
20
|
-
* ✅ Bonus! [Blur](#blurtint) support on iOS 😎
|
|
19
|
+
* ✅ Bonus! [Blur](#blurtint) support on IOS 😎
|
|
21
20
|
|
|
22
21
|
## Installation
|
|
23
22
|
|
|
@@ -29,9 +28,11 @@ yarn add @lodev09/react-native-true-sheet
|
|
|
29
28
|
npm i @lodev09/react-native-true-sheet
|
|
30
29
|
```
|
|
31
30
|
|
|
31
|
+
> This package is not compatible with [Expo Go](https://docs.expo.dev/get-started/expo-go/). Use this with [Expo CNG](https://docs.expo.dev/workflow/continuous-native-generation/) instead.
|
|
32
|
+
|
|
32
33
|
## Usage
|
|
33
34
|
|
|
34
|
-
```
|
|
35
|
+
```tsx
|
|
35
36
|
import { TrueSheet } from "@lodev09/react-native-true-sheet"
|
|
36
37
|
|
|
37
38
|
// ...
|
|
@@ -65,6 +66,7 @@ Extends `ViewProps`
|
|
|
65
66
|
| Prop | Type | Default | Description | 🍎 | 🤖 |
|
|
66
67
|
| - | - | - | - | - | - |
|
|
67
68
|
| sizes | [`SheetSize[]`](#sheetsize) | `["medium", "large"]` | Array of sizes you want the sheet to support. Maximum of _**3 sizes**_ only! **_collapsed_**, **_half-expanded_**, and **_expanded_**. Example: `size={["auto", "60%", "large"]}`| ✅ | ✅ |
|
|
69
|
+
| name | `string` | - | The name to reference this sheet. It has to be **_unique_**. You can then present this sheet globally using its name. | ✅ | ✅ |
|
|
68
70
|
| backgroundColor | `ColorValue` | `"white"` | The sheet's background color. | ✅ | ✅ |
|
|
69
71
|
| cornerRadius | `number` | - | the sheet corner radius. | ✅ | ✅ |
|
|
70
72
|
| maxHeight | `number` | - | Overrides `"large"` or `"100%"` height. | ✅ | ✅ |
|
|
@@ -73,12 +75,12 @@ Extends `ViewProps`
|
|
|
73
75
|
| dismissible | `boolean` | `true` | If set to `false`, the sheet will prevent interactive dismissal via dragging or clicking outside of it. | ✅ | ✅ |
|
|
74
76
|
| grabber | `boolean` | `true` | Shows a grabber (or handle). Native on IOS and styled `View` on Android. | ✅ | ✅ |
|
|
75
77
|
| grabberProps | [`TrueSheetGrabberProps`](#truesheetgrabberprops) | - | Overrides the grabber props for android. | | ✅ |
|
|
76
|
-
| blurTint | [`BlurTint`](#blurtint) | - | The blur effect style on
|
|
77
|
-
| scrollRef | `RefObject<...>` | - | The main scrollable ref that the sheet should handle on
|
|
78
|
+
| blurTint | [`BlurTint`](#blurtint) | - | The blur effect style on IOS. Overrides `backgroundColor` if set. Example: `"light"`, `"dark"`, etc. | ✅ | |
|
|
79
|
+
| scrollRef | `RefObject<...>` | - | The main scrollable ref that the sheet should handle on IOS. | ✅ | |
|
|
78
80
|
|
|
79
81
|
## Methods
|
|
80
82
|
|
|
81
|
-
```
|
|
83
|
+
```tsx
|
|
82
84
|
const sheet = useRef<TrueSheet>(null)
|
|
83
85
|
|
|
84
86
|
const resize = () => {
|
|
@@ -106,9 +108,40 @@ return (
|
|
|
106
108
|
| resize | `index: number` | Resizes the sheet programmatically by `index`. This is an alias of the `present(index)` method. |
|
|
107
109
|
| dismiss | - | Dismisses the sheet. |
|
|
108
110
|
|
|
109
|
-
|
|
111
|
+
### Static Methods
|
|
112
|
+
|
|
113
|
+
You can also call the above methods statically without having access to a sheet's `ref`. This is particularly useful when you want to present a sheet from anywhere.
|
|
114
|
+
|
|
115
|
+
The API is similar to the ref methods except for the required `name` prop.
|
|
110
116
|
|
|
111
117
|
```ts
|
|
118
|
+
TrueSheet.present('SHEET-NAME')
|
|
119
|
+
TrueSheet.dismiss('SHEET-NAME')
|
|
120
|
+
TrueSheet.resize('SHEET-NAME', 1)
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Example:
|
|
124
|
+
```tsx
|
|
125
|
+
// Define the sheet as usual
|
|
126
|
+
<TrueSheet name="my-sheet">
|
|
127
|
+
// ...
|
|
128
|
+
</TrueSheet>
|
|
129
|
+
```
|
|
130
|
+
```tsx
|
|
131
|
+
// Somewhere in your screen
|
|
132
|
+
const presentMySheet = async () => {
|
|
133
|
+
await TrueSheet.present('my-sheet')
|
|
134
|
+
console.log('🎉')
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return (
|
|
138
|
+
<Button onPress={presentMySheet} />
|
|
139
|
+
)
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Events
|
|
143
|
+
|
|
144
|
+
```tsx
|
|
112
145
|
const handleSizeChange = (info: SizeInfo) => {
|
|
113
146
|
console.log(info)
|
|
114
147
|
}
|
|
@@ -130,7 +163,7 @@ return (
|
|
|
130
163
|
|
|
131
164
|
### `SheetSize`
|
|
132
165
|
|
|
133
|
-
```
|
|
166
|
+
```tsx
|
|
134
167
|
<TrueSheet sizes={['auto', '80%', 'large']}>
|
|
135
168
|
// ...
|
|
136
169
|
</TrueSheet>
|
|
@@ -142,8 +175,8 @@ return (
|
|
|
142
175
|
| `"small"` | Translates to 25% | **_16+_** | ✅ |
|
|
143
176
|
| `"medium"` | Translates to 50% | **_15+_** | ✅ |
|
|
144
177
|
| `"large"` | Translates to 100% | ✅ | ✅ |
|
|
178
|
+
| `"${number}%"` | Fixed height in % | **_16+_** | ✅ |
|
|
145
179
|
| `number` | Fixed height | **_16+_** | ✅ |
|
|
146
|
-
| `${number}%` | Fixed height in % | **_16+_** | ✅ |
|
|
147
180
|
|
|
148
181
|
> [!NOTE]
|
|
149
182
|
> `auto` is not guaranteed to be accurate if your content depends on various rendering logic. Experiment with it and try to keep your content size as fixed as possible.
|
|
@@ -164,9 +197,9 @@ Grabber props to be used for android grabber or handle.
|
|
|
164
197
|
|
|
165
198
|
### `BlurTint`
|
|
166
199
|
|
|
167
|
-
Blur tint that is mapped into native values in
|
|
200
|
+
Blur tint that is mapped into native values in IOS.
|
|
168
201
|
|
|
169
|
-
```
|
|
202
|
+
```tsx
|
|
170
203
|
<TrueSheet blurTint="dark">
|
|
171
204
|
// ...
|
|
172
205
|
</TrueSheet>
|
|
@@ -200,7 +233,7 @@ Blur tint that is mapped into native values in iOS.
|
|
|
200
233
|
|
|
201
234
|
`Object` that comes with some events.
|
|
202
235
|
|
|
203
|
-
```
|
|
236
|
+
```tsx
|
|
204
237
|
{
|
|
205
238
|
index: 1,
|
|
206
239
|
value: 69
|
|
@@ -212,32 +245,101 @@ Blur tint that is mapped into native values in iOS.
|
|
|
212
245
|
| index | `number` | The size index from the provided sizes. See `sizes` prop. |
|
|
213
246
|
| value | `number` | The actual height value of the size. |
|
|
214
247
|
|
|
248
|
+
## Testing
|
|
249
|
+
|
|
250
|
+
When using `jest`, simply mock the entire package.
|
|
251
|
+
|
|
252
|
+
```tsx
|
|
253
|
+
jest.mock('@lodev09/react-native-true-sheet')
|
|
254
|
+
```
|
|
255
|
+
|
|
215
256
|
## Troubleshooting
|
|
216
257
|
|
|
258
|
+
### Presenting a sheet on top of an existing sheet on **IOS**
|
|
259
|
+
|
|
260
|
+
On IOS, presenting a sheet on top of an existing sheet will cause error.
|
|
261
|
+
|
|
262
|
+
```console
|
|
263
|
+
Attempt to present <TrueSheet.TrueSheetViewController: 0x11829f800> on <UIViewController: 0x10900eb10> (from <RNSScreen: 0x117dbf400>) which is already presenting <TrueSheet.TrueSheetViewController: 0x11a0b9200>
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
There are _two_ ways to resolve this.
|
|
267
|
+
|
|
268
|
+
1. Dismiss the "parent" sheet first
|
|
269
|
+
```tsx
|
|
270
|
+
const presentSheet2 = async () => {
|
|
271
|
+
await sheet1.current?.dismiss() // Wait for sheet 1 to dismiss ✅
|
|
272
|
+
await sheet2.current?.present() // Sheet 2 will now present 🎉
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
return (
|
|
276
|
+
<>
|
|
277
|
+
<TrueSheet ref={sheet1}>
|
|
278
|
+
<Button onPress={presentSheet2} title="Present Sheet 2" />
|
|
279
|
+
// ...
|
|
280
|
+
</TrueSheet>
|
|
281
|
+
|
|
282
|
+
<TrueSheet ref={sheet2}>
|
|
283
|
+
// ...
|
|
284
|
+
</TrueSheet>
|
|
285
|
+
</>
|
|
286
|
+
)
|
|
287
|
+
```
|
|
288
|
+
2. Define the 2nd sheet within the "parent" sheet. IOS handles this automatically by default 😎.
|
|
289
|
+
```tsx
|
|
290
|
+
const presentSheet2 = async () => {
|
|
291
|
+
await sheet2.current?.present() // Sheet 2 will now present 🎉
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
return (
|
|
295
|
+
<TrueSheet ref={sheet1}>
|
|
296
|
+
<Button onPress={presentSheet2} title="Present Sheet 2" />
|
|
297
|
+
|
|
298
|
+
// ...
|
|
299
|
+
|
|
300
|
+
<TrueSheet ref={sheet2}>
|
|
301
|
+
// ...
|
|
302
|
+
</TrueSheet>
|
|
303
|
+
</TrueSheet>
|
|
304
|
+
)
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### Handling `ScrollView` on **Android**
|
|
308
|
+
|
|
309
|
+
On Android, `nestedScrollEnabled` needs to be enabled so that scrolling works when the sheet is expanded to its `maxHeight`.
|
|
310
|
+
|
|
311
|
+
```tsx
|
|
312
|
+
<TrueSheet ref={sheet}>
|
|
313
|
+
<ScrollView nestedScrollEnabled>
|
|
314
|
+
// ...
|
|
315
|
+
</ScrollView>
|
|
316
|
+
</TrueSheet>
|
|
317
|
+
```
|
|
318
|
+
|
|
217
319
|
### Using `react-native-gesture-handler` on **Android**
|
|
218
320
|
|
|
219
321
|
On Android, RNGH does not work by default because modals are not located under React Native Root view in native hierarchy. To fix that, components need to be wrapped with `GestureHandlerRootView`.
|
|
220
322
|
|
|
221
323
|
Example:
|
|
222
|
-
```
|
|
324
|
+
```tsx
|
|
223
325
|
import { GestureHandlerRootView } from 'react-native-gesture-handler'
|
|
224
326
|
```
|
|
225
|
-
```
|
|
327
|
+
```tsx
|
|
226
328
|
return (
|
|
227
329
|
<TrueSheet ref={sheet}>
|
|
228
330
|
<GestureHandlerRootView>
|
|
229
|
-
|
|
331
|
+
// ...
|
|
230
332
|
</GestureHandlerRootView>
|
|
231
333
|
</TrueSheet>
|
|
232
334
|
)
|
|
233
335
|
```
|
|
234
336
|
|
|
235
|
-
### Integrating `@react-navigation/native` on
|
|
337
|
+
### Integrating `@react-navigation/native` on **IOS**
|
|
236
338
|
|
|
237
|
-
On
|
|
339
|
+
On IOS, navigating to a [React Navigation](https://reactnavigation.org) screen from within the Sheet can cause issues. To resolve this, dismiss the sheet before navigating!
|
|
238
340
|
|
|
239
341
|
Example:
|
|
240
|
-
```
|
|
342
|
+
```tsx
|
|
241
343
|
const sheet = useRef<TrueSheet>(null)
|
|
242
344
|
|
|
243
345
|
const navigate = async () => {
|
|
@@ -3,38 +3,34 @@ package com.lodev09.truesheet
|
|
|
3
3
|
import android.graphics.Color
|
|
4
4
|
import android.view.ViewGroup
|
|
5
5
|
import android.view.WindowManager
|
|
6
|
-
import android.widget.LinearLayout
|
|
7
|
-
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
|
8
6
|
import com.facebook.react.uimanager.ThemedReactContext
|
|
7
|
+
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
|
9
8
|
import com.google.android.material.bottomsheet.BottomSheetDialog
|
|
10
9
|
import com.lodev09.truesheet.core.KeyboardManager
|
|
11
|
-
import com.lodev09.truesheet.core.
|
|
10
|
+
import com.lodev09.truesheet.core.RootSheetView
|
|
12
11
|
import com.lodev09.truesheet.core.Utils
|
|
13
12
|
|
|
14
|
-
class
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
) : BottomSheetDialog(reactContext) {
|
|
13
|
+
data class SizeInfo(val index: Int, val value: Float)
|
|
14
|
+
|
|
15
|
+
class TrueSheetDialog(private val reactContext: ThemedReactContext, private val rootSheetView: RootSheetView) :
|
|
16
|
+
BottomSheetDialog(reactContext) {
|
|
19
17
|
|
|
20
18
|
private var keyboardManager = KeyboardManager(reactContext)
|
|
21
19
|
|
|
22
|
-
var
|
|
20
|
+
var maxScreenHeight: Int = 0
|
|
21
|
+
var maxSheetHeight: Int? = null
|
|
23
22
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
addView(rootViewGroup)
|
|
27
|
-
setContentView(this)
|
|
23
|
+
var contentView: ViewGroup? = null
|
|
24
|
+
var footerView: ViewGroup? = null
|
|
28
25
|
|
|
29
|
-
|
|
26
|
+
var sizes: Array<Any> = arrayOf("medium", "large")
|
|
30
27
|
|
|
31
|
-
|
|
32
|
-
sheetView.setBackgroundColor(Color.TRANSPARENT)
|
|
28
|
+
private var sheetView: ViewGroup
|
|
33
29
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
30
|
+
init {
|
|
31
|
+
setContentView(rootSheetView)
|
|
32
|
+
sheetView = rootSheetView.parent as ViewGroup
|
|
33
|
+
sheetView.setBackgroundColor(Color.TRANSPARENT)
|
|
38
34
|
|
|
39
35
|
// Setup window params to adjust layout based on Keyboard state.
|
|
40
36
|
window?.apply {
|
|
@@ -43,19 +39,111 @@ class TrueSheetDialog(
|
|
|
43
39
|
WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
|
|
44
40
|
)
|
|
45
41
|
}
|
|
42
|
+
|
|
43
|
+
// Update the usable sheet height
|
|
44
|
+
maxScreenHeight = Utils.screenHeight(reactContext)
|
|
46
45
|
}
|
|
47
46
|
|
|
48
47
|
fun show(sizeIndex: Int) {
|
|
49
48
|
if (isShowing) {
|
|
50
|
-
|
|
49
|
+
setStateForSizeIndex(sizeIndex)
|
|
51
50
|
} else {
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
configure()
|
|
52
|
+
setStateForSizeIndex(sizeIndex)
|
|
54
53
|
|
|
55
54
|
this.show()
|
|
56
55
|
}
|
|
57
56
|
}
|
|
58
57
|
|
|
58
|
+
fun positionFooter() {
|
|
59
|
+
footerView?.apply {
|
|
60
|
+
y = (maxScreenHeight - sheetView.top - height).toFloat()
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Set the state based on the given size index.
|
|
66
|
+
*/
|
|
67
|
+
private fun setStateForSizeIndex(index: Int) {
|
|
68
|
+
behavior.state = getStateForSizeIndex(index)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Get the height value based on the size config value.
|
|
73
|
+
*/
|
|
74
|
+
private fun getSizeHeight(size: Any, contentHeight: Int): Int {
|
|
75
|
+
val height =
|
|
76
|
+
when (size) {
|
|
77
|
+
is Double -> Utils.toPixel(size)
|
|
78
|
+
|
|
79
|
+
is Int -> Utils.toPixel(size.toDouble())
|
|
80
|
+
|
|
81
|
+
is String -> {
|
|
82
|
+
when (size) {
|
|
83
|
+
"auto" -> contentHeight
|
|
84
|
+
|
|
85
|
+
"large" -> maxScreenHeight
|
|
86
|
+
|
|
87
|
+
"medium" -> (maxScreenHeight * 0.50).toInt()
|
|
88
|
+
|
|
89
|
+
"small" -> (maxScreenHeight * 0.25).toInt()
|
|
90
|
+
|
|
91
|
+
else -> {
|
|
92
|
+
if (size.endsWith('%')) {
|
|
93
|
+
val percent = size.trim('%').toDoubleOrNull()
|
|
94
|
+
if (percent == null) {
|
|
95
|
+
0
|
|
96
|
+
} else {
|
|
97
|
+
((percent / 100) * maxScreenHeight).toInt()
|
|
98
|
+
}
|
|
99
|
+
} else {
|
|
100
|
+
val fixedHeight = size.toDoubleOrNull()
|
|
101
|
+
if (fixedHeight == null) {
|
|
102
|
+
0
|
|
103
|
+
} else {
|
|
104
|
+
Utils.toPixel(fixedHeight)
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
else -> (maxScreenHeight * 0.5).toInt()
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return when (maxSheetHeight) {
|
|
115
|
+
null -> height
|
|
116
|
+
else -> minOf(height, maxSheetHeight ?: maxScreenHeight)
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Determines the state based on the given size index.
|
|
122
|
+
*/
|
|
123
|
+
private fun getStateForSizeIndex(index: Int) =
|
|
124
|
+
when (sizes.size) {
|
|
125
|
+
1 -> BottomSheetBehavior.STATE_EXPANDED
|
|
126
|
+
|
|
127
|
+
2 -> {
|
|
128
|
+
when (index) {
|
|
129
|
+
0 -> BottomSheetBehavior.STATE_COLLAPSED
|
|
130
|
+
1 -> BottomSheetBehavior.STATE_EXPANDED
|
|
131
|
+
else -> BottomSheetBehavior.STATE_HIDDEN
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
3 -> {
|
|
136
|
+
when (index) {
|
|
137
|
+
0 -> BottomSheetBehavior.STATE_COLLAPSED
|
|
138
|
+
1 -> BottomSheetBehavior.STATE_HALF_EXPANDED
|
|
139
|
+
2 -> BottomSheetBehavior.STATE_EXPANDED
|
|
140
|
+
else -> BottomSheetBehavior.STATE_HIDDEN
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
else -> BottomSheetBehavior.STATE_HIDDEN
|
|
145
|
+
}
|
|
146
|
+
|
|
59
147
|
/**
|
|
60
148
|
* Handle keyboard state changes and adjust maxScreenHeight (sheet max height) accordingly.
|
|
61
149
|
* Also update footer's Y position.
|
|
@@ -63,14 +151,12 @@ class TrueSheetDialog(
|
|
|
63
151
|
fun registerKeyboardManager() {
|
|
64
152
|
keyboardManager.registerKeyboardListener(object : KeyboardManager.OnKeyboardListener {
|
|
65
153
|
override fun onKeyboardStateChange(isVisible: Boolean, visibleHeight: Int?) {
|
|
66
|
-
when (isVisible) {
|
|
67
|
-
true ->
|
|
68
|
-
else ->
|
|
154
|
+
maxScreenHeight = when (isVisible) {
|
|
155
|
+
true -> visibleHeight ?: 0
|
|
156
|
+
else -> Utils.screenHeight(reactContext)
|
|
69
157
|
}
|
|
70
158
|
|
|
71
|
-
|
|
72
|
-
y = (behavior.maxScreenHeight - (sheetView.top ?: 0) - height).toFloat()
|
|
73
|
-
}
|
|
159
|
+
positionFooter()
|
|
74
160
|
}
|
|
75
161
|
})
|
|
76
162
|
}
|
|
@@ -82,6 +168,90 @@ class TrueSheetDialog(
|
|
|
82
168
|
keyboardManager.unregisterKeyboardListener()
|
|
83
169
|
}
|
|
84
170
|
|
|
171
|
+
/**
|
|
172
|
+
* Configure the sheet based on size preferences.
|
|
173
|
+
*/
|
|
174
|
+
fun configure() {
|
|
175
|
+
var contentHeight = 0
|
|
176
|
+
|
|
177
|
+
contentView?.let { contentHeight = it.height }
|
|
178
|
+
footerView?.let { contentHeight += it.height }
|
|
179
|
+
|
|
180
|
+
// Configure sheet sizes
|
|
181
|
+
behavior.apply {
|
|
182
|
+
skipCollapsed = false
|
|
183
|
+
isFitToContents = true
|
|
184
|
+
|
|
185
|
+
// m3 max width 640dp
|
|
186
|
+
maxWidth = Utils.toPixel(640.0)
|
|
187
|
+
|
|
188
|
+
when (sizes.size) {
|
|
189
|
+
1 -> {
|
|
190
|
+
maxHeight = getSizeHeight(sizes[0], contentHeight)
|
|
191
|
+
setPeekHeight(maxHeight, isShowing)
|
|
192
|
+
skipCollapsed = true
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
2 -> {
|
|
196
|
+
setPeekHeight(getSizeHeight(sizes[0], contentHeight), isShowing)
|
|
197
|
+
maxHeight = getSizeHeight(sizes[1], contentHeight)
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
3 -> {
|
|
201
|
+
// Enables half expanded
|
|
202
|
+
isFitToContents = false
|
|
203
|
+
|
|
204
|
+
setPeekHeight(getSizeHeight(sizes[0], contentHeight), isShowing)
|
|
205
|
+
halfExpandedRatio = getSizeHeight(sizes[1], contentHeight).toFloat() / maxScreenHeight.toFloat()
|
|
206
|
+
maxHeight = getSizeHeight(sizes[2], contentHeight)
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Get the SizeInfo data by state.
|
|
214
|
+
*/
|
|
215
|
+
fun getSizeInfoForState(state: Int): SizeInfo? =
|
|
216
|
+
when (sizes.size) {
|
|
217
|
+
1 -> {
|
|
218
|
+
when (state) {
|
|
219
|
+
BottomSheetBehavior.STATE_EXPANDED -> SizeInfo(0, Utils.toDIP(behavior.maxHeight))
|
|
220
|
+
else -> null
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
2 -> {
|
|
225
|
+
when (state) {
|
|
226
|
+
BottomSheetBehavior.STATE_COLLAPSED -> SizeInfo(0, Utils.toDIP(behavior.peekHeight))
|
|
227
|
+
BottomSheetBehavior.STATE_EXPANDED -> SizeInfo(1, Utils.toDIP(behavior.maxHeight))
|
|
228
|
+
else -> null
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
3 -> {
|
|
233
|
+
when (state) {
|
|
234
|
+
BottomSheetBehavior.STATE_COLLAPSED -> SizeInfo(0, Utils.toDIP(behavior.peekHeight))
|
|
235
|
+
|
|
236
|
+
BottomSheetBehavior.STATE_HALF_EXPANDED -> {
|
|
237
|
+
val height = behavior.halfExpandedRatio * maxScreenHeight
|
|
238
|
+
SizeInfo(1, Utils.toDIP(height.toInt()))
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
BottomSheetBehavior.STATE_EXPANDED -> SizeInfo(2, Utils.toDIP(behavior.maxHeight))
|
|
242
|
+
|
|
243
|
+
else -> null
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
else -> null
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Get SizeInfo data for given size index.
|
|
252
|
+
*/
|
|
253
|
+
fun getSizeInfoForIndex(index: Int) = getSizeInfoForState(getStateForSizeIndex(index)) ?: SizeInfo(0, 0f)
|
|
254
|
+
|
|
85
255
|
companion object {
|
|
86
256
|
const val TAG = "TrueSheetView"
|
|
87
257
|
}
|