Skip to content

Commit 58f3773

Browse files
authored
Fix: Sheet background (#114)
* chore: cleanup * fix: ios background color * chore: tidy * fix: add edge-to-edge to sample sheets * fix(android): drag bug * fix: default initial index * fix: android background
1 parent c92aa98 commit 58f3773

22 files changed

+338
-83
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,6 @@ android/generated
8484

8585
# Docs
8686
.vercel
87+
88+
# Misc
89+
.xcode.env.local

android/src/main/java/com/lodev09/truesheet/TrueSheetDialog.kt

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package com.lodev09.truesheet
22

33
import android.annotation.SuppressLint
44
import android.graphics.Color
5+
import android.graphics.drawable.ShapeDrawable
6+
import android.graphics.drawable.shapes.RoundRectShape
57
import android.view.View
68
import android.view.ViewGroup
79
import android.view.WindowManager
@@ -38,6 +40,7 @@ class TrueSheetDialog(private val reactContext: ThemedReactContext, private val
3840
* The maximum window height
3941
*/
4042
var maxScreenHeight = 0
43+
4144
var contentHeight = 0
4245
var footerHeight = 0
4346
var maxSheetHeight: Int? = null
@@ -57,12 +60,15 @@ class TrueSheetDialog(private val reactContext: ThemedReactContext, private val
5760
behavior.isHideable = value
5861
}
5962

63+
var cornerRadius: Float = 0f
64+
var backgroundColor: Int = Color.WHITE
6065
var footerView: ViewGroup? = null
6166

6267
var sizes: Array<Any> = arrayOf("medium", "large")
6368

6469
init {
6570
setContentView(rootSheetView)
71+
6672
sheetView = rootSheetView.parent as ViewGroup
6773
sheetView.setBackgroundColor(Color.TRANSPARENT)
6874

@@ -93,6 +99,18 @@ class TrueSheetDialog(private val reactContext: ThemedReactContext, private val
9399
}
94100
}
95101

102+
/**
103+
* Setup background color and corner radius.
104+
*/
105+
fun setupBackground() {
106+
val outerRadii = FloatArray(8) { cornerRadius }
107+
val background = ShapeDrawable(RoundRectShape(outerRadii, null, null))
108+
109+
// Use current background color
110+
background.paint.color = backgroundColor
111+
sheetView.background = background
112+
}
113+
96114
/**
97115
* Setup dimmed sheet.
98116
* `dimmedIndex` will further customize the dimming behavior.
@@ -171,11 +189,11 @@ class TrueSheetDialog(private val reactContext: ThemedReactContext, private val
171189
* Get the height value based on the size config value.
172190
*/
173191
private fun getSizeHeight(size: Any): Int {
174-
val height =
192+
val height: Int =
175193
when (size) {
176-
is Double -> Utils.toPixel(size)
194+
is Double -> Utils.toPixel(size).toInt()
177195

178-
is Int -> Utils.toPixel(size.toDouble())
196+
is Int -> Utils.toPixel(size.toDouble()).toInt()
179197

180198
is String -> {
181199
when (size) {
@@ -200,7 +218,7 @@ class TrueSheetDialog(private val reactContext: ThemedReactContext, private val
200218
if (fixedHeight == null) {
201219
0
202220
} else {
203-
Utils.toPixel(fixedHeight)
221+
Utils.toPixel(fixedHeight).toInt()
204222
}
205223
}
206224
}
@@ -278,7 +296,7 @@ class TrueSheetDialog(private val reactContext: ThemedReactContext, private val
278296
isFitToContents = true
279297

280298
// m3 max width 640dp
281-
maxWidth = Utils.toPixel(640.0)
299+
maxWidth = Utils.toPixel(640.0).toInt()
282300

283301
when (sizes.size) {
284302
1 -> {
@@ -311,29 +329,29 @@ class TrueSheetDialog(private val reactContext: ThemedReactContext, private val
311329
when (sizes.size) {
312330
1 -> {
313331
when (state) {
314-
BottomSheetBehavior.STATE_EXPANDED -> SizeInfo(0, Utils.toDIP(behavior.maxHeight))
332+
BottomSheetBehavior.STATE_EXPANDED -> SizeInfo(0, Utils.toDIP(behavior.maxHeight.toFloat()))
315333
else -> null
316334
}
317335
}
318336

319337
2 -> {
320338
when (state) {
321-
BottomSheetBehavior.STATE_COLLAPSED -> SizeInfo(0, Utils.toDIP(behavior.peekHeight))
322-
BottomSheetBehavior.STATE_EXPANDED -> SizeInfo(1, Utils.toDIP(behavior.maxHeight))
339+
BottomSheetBehavior.STATE_COLLAPSED -> SizeInfo(0, Utils.toDIP(behavior.peekHeight.toFloat()))
340+
BottomSheetBehavior.STATE_EXPANDED -> SizeInfo(1, Utils.toDIP(behavior.maxHeight.toFloat()))
323341
else -> null
324342
}
325343
}
326344

327345
3 -> {
328346
when (state) {
329-
BottomSheetBehavior.STATE_COLLAPSED -> SizeInfo(0, Utils.toDIP(behavior.peekHeight))
347+
BottomSheetBehavior.STATE_COLLAPSED -> SizeInfo(0, Utils.toDIP(behavior.peekHeight.toFloat()))
330348

331349
BottomSheetBehavior.STATE_HALF_EXPANDED -> {
332350
val height = behavior.halfExpandedRatio * maxScreenHeight
333-
SizeInfo(1, Utils.toDIP(height.toInt()))
351+
SizeInfo(1, Utils.toDIP(height))
334352
}
335353

336-
BottomSheetBehavior.STATE_EXPANDED -> SizeInfo(2, Utils.toDIP(behavior.maxHeight))
354+
BottomSheetBehavior.STATE_EXPANDED -> SizeInfo(2, Utils.toDIP(behavior.maxHeight.toFloat()))
337355

338356
else -> null
339357
}

android/src/main/java/com/lodev09/truesheet/TrueSheetView.kt

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ class TrueSheetView(context: Context) :
3636
/**
3737
* Current activeIndex.
3838
*/
39-
private var currentSizeIndex: Int = 0
39+
private var currentSizeIndex: Int = -1
4040

4141
/**
4242
* Promise callback to be invoked after `present` is called.
@@ -70,7 +70,7 @@ class TrueSheetView(context: Context) :
7070
// Configure Sheet Dialog
7171
sheetDialog.apply {
7272
setOnSizeChangeListener { w, h ->
73-
eventDispatcher?.dispatchEvent(ContainerSizeChangeEvent(surfaceId, id, Utils.toDIP(w), Utils.toDIP(h)))
73+
eventDispatcher?.dispatchEvent(ContainerSizeChangeEvent(surfaceId, id, Utils.toDIP(w.toFloat()), Utils.toDIP(h.toFloat())))
7474
}
7575

7676
// Setup listener when the dialog has been presented.
@@ -289,6 +289,20 @@ class TrueSheetView(context: Context) :
289289
}
290290
}
291291

292+
fun setCornerRadius(radius: Float) {
293+
if (sheetDialog.cornerRadius == radius) return
294+
295+
sheetDialog.cornerRadius = radius
296+
sheetDialog.setupBackground()
297+
}
298+
299+
fun setBackground(color: Int) {
300+
if (sheetDialog.backgroundColor == color) return
301+
302+
sheetDialog.backgroundColor = color
303+
sheetDialog.setupBackground()
304+
}
305+
292306
fun setSoftInputMode(mode: Int) {
293307
sheetDialog.window?.apply {
294308
this.setSoftInputMode(mode)

android/src/main/java/com/lodev09/truesheet/TrueSheetViewManager.kt

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.lodev09.truesheet
22

3+
import android.graphics.Color
34
import android.util.Log
45
import android.view.WindowManager
56
import com.facebook.react.bridge.ReadableArray
@@ -41,7 +42,7 @@ class TrueSheetViewManager : ViewGroupManager<TrueSheetView>() {
4142

4243
@ReactProp(name = "maxHeight")
4344
fun setMaxHeight(view: TrueSheetView, height: Double) {
44-
view.setMaxHeight(Utils.toPixel(height))
45+
view.setMaxHeight(Utils.toPixel(height).toInt())
4546
}
4647

4748
@ReactProp(name = "dismissible")
@@ -81,12 +82,23 @@ class TrueSheetViewManager : ViewGroupManager<TrueSheetView>() {
8182

8283
@ReactProp(name = "contentHeight")
8384
fun setContentHeight(view: TrueSheetView, height: Double) {
84-
view.setContentHeight(Utils.toPixel(height))
85+
view.setContentHeight(Utils.toPixel(height).toInt())
8586
}
8687

8788
@ReactProp(name = "footerHeight")
8889
fun setFooterHeight(view: TrueSheetView, height: Double) {
89-
view.setFooterHeight(Utils.toPixel(height))
90+
view.setFooterHeight(Utils.toPixel(height).toInt())
91+
}
92+
93+
@ReactProp(name = "cornerRadius")
94+
fun setCornerRadius(view: TrueSheetView, radius: Double) {
95+
view.setCornerRadius(Utils.toPixel(radius))
96+
}
97+
98+
@ReactProp(name = "background")
99+
fun setBackground(view: TrueSheetView, colorName: String) {
100+
val color = runCatching { Color.parseColor(colorName) }.getOrDefault(Color.WHITE)
101+
view.setBackground(color)
90102
}
91103

92104
@ReactProp(name = "sizes")

android/src/main/java/com/lodev09/truesheet/core/RootSheetView.kt

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,12 @@ import com.facebook.react.views.view.ReactViewGroup
2727
class RootSheetView(private val context: Context?) :
2828
ReactViewGroup(context),
2929
RootView {
30-
private var hasAdjustedSize = false
3130
private var viewWidth = 0
3231
private var viewHeight = 0
3332

3433
private val jSTouchDispatcher = JSTouchDispatcher(this)
3534
private var jSPointerDispatcher: JSPointerDispatcher? = null
36-
public var sizeChangeListener: ((w: Int, h: Int) -> Unit)? = null
35+
var sizeChangeListener: ((w: Int, h: Int) -> Unit)? = null
3736

3837
var eventDispatcher: EventDispatcher? = null
3938

@@ -43,37 +42,31 @@ class RootSheetView(private val context: Context?) :
4342
}
4443
}
4544

45+
private val reactContext: ThemedReactContext
46+
get() = context as ThemedReactContext
47+
48+
private fun updateContainerSize() {
49+
sizeChangeListener?.let { it(viewWidth, viewHeight) }
50+
}
51+
4652
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
4753
super.onSizeChanged(w, h, oldw, oldh)
4854

4955
viewWidth = w
5056
viewHeight = h
51-
updateFirstChildView()
52-
}
5357

54-
private fun updateFirstChildView() {
55-
if (childCount > 0) {
56-
hasAdjustedSize = false
57-
sizeChangeListener?.let { it(viewWidth, viewHeight) }
58-
} else {
59-
hasAdjustedSize = true
60-
}
58+
updateContainerSize()
6159
}
6260

6361
override fun addView(child: View, index: Int, params: LayoutParams) {
6462
super.addView(child, index, params)
65-
if (hasAdjustedSize) {
66-
updateFirstChildView()
67-
}
63+
updateContainerSize()
6864
}
6965

7066
override fun handleException(t: Throwable) {
7167
reactContext.reactApplicationContext.handleException(RuntimeException(t))
7268
}
7369

74-
private val reactContext: ThemedReactContext
75-
get() = context as ThemedReactContext
76-
7770
override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
7871
eventDispatcher?.let { jSTouchDispatcher.handleTouchEvent(event, it) }
7972
jSPointerDispatcher?.handleMotionEvent(event, eventDispatcher, true)

android/src/main/java/com/lodev09/truesheet/core/Utils.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ object Utils {
5757
}
5858
}
5959

60-
fun toDIP(value: Int): Float = PixelUtil.toDIPFromPixel(value.toFloat())
61-
fun toPixel(value: Double): Int = PixelUtil.toPixelFromDIP(value).toInt()
60+
fun toDIP(value: Float): Float = PixelUtil.toDIPFromPixel(value)
61+
fun toPixel(value: Double): Float = PixelUtil.toPixelFromDIP(value)
6262

6363
fun withPromise(promise: Promise, closure: () -> Any?) {
6464
try {

docs/docs/reference/01-props.mdx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ The sheet's background color.
5151
| - | - | - | - |
5252
| `ColorValue` | `"white"` |||
5353

54+
:::info
55+
This prop only supports HEX and named colors. Example: `#282e37ff`, `blue`.
56+
:::
57+
5458
### `cornerRadius`
5559

5660
The sheet corner radius.

example/ios/.xcode.env.local

Lines changed: 0 additions & 1 deletion
This file was deleted.

example/ios/Podfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
ENV['RCT_NEW_ARCH_ENABLED'] = '1'
2+
13
# Resolve react_native_pods.rb with node to allow for hoisting
24
require Pod::Executable.execute_command('node', ['-p',
35
'require.resolve(

example/ios/Podfile.lock

Lines changed: 3 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1244,7 +1244,7 @@ PODS:
12441244
- Yoga
12451245
- react-native-maps (1.20.1):
12461246
- React-Core
1247-
- react-native-true-sheet (0.1.0):
1247+
- react-native-true-sheet (1.0.3):
12481248
- DoubleConversion
12491249
- glog
12501250
- hermes-engine
@@ -1532,27 +1532,6 @@ PODS:
15321532
- React-logger (= 0.76.3)
15331533
- React-perflogger (= 0.76.3)
15341534
- React-utils (= 0.76.3)
1535-
- RNGestureHandler (2.21.2):
1536-
- DoubleConversion
1537-
- glog
1538-
- hermes-engine
1539-
- RCT-Folly (= 2024.01.01.00)
1540-
- RCTRequired
1541-
- RCTTypeSafety
1542-
- React-Core
1543-
- React-debug
1544-
- React-Fabric
1545-
- React-featureflags
1546-
- React-graphics
1547-
- React-ImageManager
1548-
- React-NativeModulesApple
1549-
- React-RCTFabric
1550-
- React-rendererdebug
1551-
- React-utils
1552-
- ReactCodegen
1553-
- ReactCommon/turbomodule/bridging
1554-
- ReactCommon/turbomodule/core
1555-
- Yoga
15561535
- RNReanimated (3.16.3):
15571536
- DoubleConversion
15581537
- glog
@@ -1710,7 +1689,6 @@ DEPENDENCIES:
17101689
- React-utils (from `../node_modules/react-native/ReactCommon/react/utils`)
17111690
- ReactCodegen (from `build/generated/ios`)
17121691
- ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
1713-
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
17141692
- RNReanimated (from `../node_modules/react-native-reanimated`)
17151693
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
17161694

@@ -1848,8 +1826,6 @@ EXTERNAL SOURCES:
18481826
:path: build/generated/ios
18491827
ReactCommon:
18501828
:path: "../node_modules/react-native/ReactCommon"
1851-
RNGestureHandler:
1852-
:path: "../node_modules/react-native-gesture-handler"
18531829
RNReanimated:
18541830
:path: "../node_modules/react-native-reanimated"
18551831
Yoga:
@@ -1892,7 +1868,7 @@ SPEC CHECKSUMS:
18921868
React-Mapbuffer: ad1ba0205205a16dbff11b8ade6d1b3959451658
18931869
React-microtasksnativemodule: e771eb9eb6ace5884ee40a293a0e14a9d7a4343c
18941870
react-native-maps: ee1e65647460c3d41e778071be5eda10e3da6225
1895-
react-native-true-sheet: 4a449f0688b0d769ef20c0e21e21d178b8fbd6dd
1871+
react-native-true-sheet: 00be9fe24ef77f41f9c70efbeb30bb5ac91c2893
18961872
React-nativeconfig: aeed6e2a8ac02b2df54476afcc7c663416c12bf7
18971873
React-NativeModulesApple: c5b7813da94136f50ef084fa1ac077332dcfc658
18981874
React-perflogger: 6afb7eebf7d9521cc70481688ccddf212970e9d3
@@ -1920,11 +1896,10 @@ SPEC CHECKSUMS:
19201896
React-utils: 2bcaf4f4dfe361344bce2fae428603d518488630
19211897
ReactCodegen: ae99a130606068ed40d1d9c0d5f25fda142a0647
19221898
ReactCommon: 89c87b343deacc8610b099ac764848f0ce937e3e
1923-
RNGestureHandler: 0e5ae8d72ef4afb855e98dcdbe60f27d938abe13
19241899
RNReanimated: 006a5d3961bf09c1e96d62ed436e02b2e43b89bb
19251900
SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748
19261901
Yoga: 3deb2471faa9916c8a82dda2a22d3fba2620ad37
19271902

1928-
PODFILE CHECKSUM: 5eaf14a39e31872a9c12e5d368593ff6b4a71d73
1903+
PODFILE CHECKSUM: b38a1c0f527446c0db5a072821b4af1c2506e252
19291904

19301905
COCOAPODS: 1.16.2

example/src/sheets/BasicSheet.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ export const BasicSheet = forwardRef((props: BasicSheetProps, ref: Ref<TrueSheet
4545
blurTint="dark"
4646
backgroundColor={DARK}
4747
cornerRadius={12}
48+
edgeToEdge
4849
grabberProps={{ color: GRABBER_COLOR }}
4950
onDismiss={() => console.log('Basic sheet dismissed!')}
5051
onPresent={({ index, value }) =>

example/src/sheets/BlankSheet.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export const BlankSheet = forwardRef((props: BlankSheetProps, ref: Ref<TrueSheet
1313
sizes={['medium', 'large']}
1414
blurTint="dark"
1515
cornerRadius={12}
16+
edgeToEdge
1617
backgroundColor={DARK}
1718
keyboardMode="pan"
1819
contentContainerStyle={styles.content}

0 commit comments

Comments
 (0)