From 3988bee7a2aba2104f2a9e3ef8320dcb1728d1af Mon Sep 17 00:00:00 2001 From: Jovanni Lo Date: Mon, 22 Apr 2024 15:56:18 +0800 Subject: [PATCH] feat: handle `auto` sizing properly (#9) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: handle `auto` sizing properly * docs: remove `auto` note 🎉 --- .../com/lodev09/truesheet/TrueSheetDialog.kt | 27 +++---- .../com/lodev09/truesheet/TrueSheetView.kt | 37 +++++---- .../lodev09/truesheet/TrueSheetViewManager.kt | 10 +++ docs/docs/reference/03-types.mdx | 6 -- example/src/sheets/PromptSheet.tsx | 35 ++------ ios/TrueSheetView.swift | 79 +++++++++---------- ios/TrueSheetViewController.swift | 8 +- ios/TrueSheetViewManager.m | 4 + src/TrueSheet.tsx | 32 +++++++- 9 files changed, 124 insertions(+), 114 deletions(-) diff --git a/android/src/main/java/com/lodev09/truesheet/TrueSheetDialog.kt b/android/src/main/java/com/lodev09/truesheet/TrueSheetDialog.kt index 7a0d911..d590b1d 100644 --- a/android/src/main/java/com/lodev09/truesheet/TrueSheetDialog.kt +++ b/android/src/main/java/com/lodev09/truesheet/TrueSheetDialog.kt @@ -18,9 +18,10 @@ class TrueSheetDialog(private val reactContext: ThemedReactContext, private val private var keyboardManager = KeyboardManager(reactContext) var maxScreenHeight: Int = 0 + var contentHeight: Int = 0 + var footerHeight: Int = 0 var maxSheetHeight: Int? = null - var contentView: ViewGroup? = null var footerView: ViewGroup? = null var sizes: Array = arrayOf("medium", "large") @@ -57,7 +58,7 @@ class TrueSheetDialog(private val reactContext: ThemedReactContext, private val fun positionFooter() { footerView?.apply { - y = (maxScreenHeight - sheetView.top - height).toFloat() + y = (maxScreenHeight - sheetView.top - footerHeight).toFloat() } } @@ -71,7 +72,7 @@ class TrueSheetDialog(private val reactContext: ThemedReactContext, private val /** * Get the height value based on the size config value. */ - private fun getSizeHeight(size: Any, contentHeight: Int): Int { + private fun getSizeHeight(size: Any): Int { val height = when (size) { is Double -> Utils.toPixel(size) @@ -80,7 +81,7 @@ class TrueSheetDialog(private val reactContext: ThemedReactContext, private val is String -> { when (size) { - "auto" -> contentHeight + "auto" -> contentHeight + footerHeight "large" -> maxScreenHeight @@ -172,11 +173,6 @@ class TrueSheetDialog(private val reactContext: ThemedReactContext, private val * Configure the sheet based on size preferences. */ fun configure() { - var contentHeight = 0 - - contentView?.let { contentHeight = it.height } - footerView?.let { contentHeight += it.height } - // Configure sheet sizes behavior.apply { skipCollapsed = false @@ -187,23 +183,22 @@ class TrueSheetDialog(private val reactContext: ThemedReactContext, private val when (sizes.size) { 1 -> { - maxHeight = getSizeHeight(sizes[0], contentHeight) - setPeekHeight(maxHeight, isShowing) + maxHeight = getSizeHeight(sizes[0]) skipCollapsed = true } 2 -> { - setPeekHeight(getSizeHeight(sizes[0], contentHeight), isShowing) - maxHeight = getSizeHeight(sizes[1], contentHeight) + setPeekHeight(getSizeHeight(sizes[0]), isShowing) + maxHeight = getSizeHeight(sizes[1]) } 3 -> { // Enables half expanded isFitToContents = false - setPeekHeight(getSizeHeight(sizes[0], contentHeight), isShowing) - halfExpandedRatio = getSizeHeight(sizes[1], contentHeight).toFloat() / maxScreenHeight.toFloat() - maxHeight = getSizeHeight(sizes[2], contentHeight) + setPeekHeight(getSizeHeight(sizes[0]), isShowing) + halfExpandedRatio = getSizeHeight(sizes[1]).toFloat() / maxScreenHeight.toFloat() + maxHeight = getSizeHeight(sizes[2]) } } } diff --git a/android/src/main/java/com/lodev09/truesheet/TrueSheetView.kt b/android/src/main/java/com/lodev09/truesheet/TrueSheetView.kt index 09ce408..b8c2eb4 100644 --- a/android/src/main/java/com/lodev09/truesheet/TrueSheetView.kt +++ b/android/src/main/java/com/lodev09/truesheet/TrueSheetView.kt @@ -52,11 +52,6 @@ class TrueSheetView(context: Context) : */ private val rootSheetView: RootSheetView - /** - * 1st child of the container view. - */ - private var contentView: ViewGroup? = null - /** * 2nd child of the container view. */ @@ -103,19 +98,17 @@ class TrueSheetView(context: Context) : // dispatch onDismiss event eventDispatcher?.dispatchEvent(DismissEvent(surfaceId, id)) } - } - // Configure sheet behavior events - sheetDialog.apply { + // Configure sheet behavior events behavior.addBottomSheetCallback( object : BottomSheetBehavior.BottomSheetCallback() { override fun onSlide(sheetView: View, slideOffset: Float) { footerView?.let { - val y = (maxScreenHeight - sheetView.top - it.height).toFloat() + val y = (maxScreenHeight - sheetView.top - footerHeight).toFloat() if (slideOffset >= 0) { it.y = y } else { - it.y = y - it.height * slideOffset + it.y = y - footerHeight * slideOffset } } } @@ -165,10 +158,8 @@ class TrueSheetView(context: Context) : (child as ViewGroup).let { // Container View's first child is the Content View - contentView = it.getChildAt(0) as ViewGroup footerView = it.getChildAt(1) as ViewGroup - sheetDialog.contentView = contentView sheetDialog.footerView = footerView // rootView's first child is the Container View @@ -218,18 +209,26 @@ class TrueSheetView(context: Context) : sheetDialog.dismiss() } - private fun configureIfPresented() { + private fun configureIfShowing() { if (sheetDialog.isShowing) { - UiThreadUtil.runOnUiThread { - sheetDialog.configure() - sheetDialog.positionFooter() - } + sheetDialog.configure() + sheetDialog.positionFooter() } } fun setMaxHeight(height: Int) { sheetDialog.maxSheetHeight = height - configureIfPresented() + configureIfShowing() + } + + fun setContentHeight(height: Int) { + sheetDialog.contentHeight = height + configureIfShowing() + } + + fun setFooterHeight(height: Int) { + sheetDialog.footerHeight = height + configureIfShowing() } fun setDismissible(dismissible: Boolean) { @@ -239,7 +238,7 @@ class TrueSheetView(context: Context) : fun setSizes(newSizes: Array) { sheetDialog.sizes = newSizes - configureIfPresented() + configureIfShowing() } /** diff --git a/android/src/main/java/com/lodev09/truesheet/TrueSheetViewManager.kt b/android/src/main/java/com/lodev09/truesheet/TrueSheetViewManager.kt index b26c439..6a2145f 100644 --- a/android/src/main/java/com/lodev09/truesheet/TrueSheetViewManager.kt +++ b/android/src/main/java/com/lodev09/truesheet/TrueSheetViewManager.kt @@ -39,6 +39,16 @@ class TrueSheetViewManager : ViewGroupManager() { view.setDismissible(dismissible) } + @ReactProp(name = "contentHeight") + fun setContentHeight(view: TrueSheetView, height: Double) { + view.setContentHeight(Utils.toPixel(height)) + } + + @ReactProp(name = "footerHeight") + fun setFooterHeight(view: TrueSheetView, height: Double) { + view.setFooterHeight(Utils.toPixel(height)) + } + @ReactProp(name = "sizes") fun setSizes(view: TrueSheetView, sizes: ReadableArray) { val result = ArrayList() diff --git a/docs/docs/reference/03-types.mdx b/docs/docs/reference/03-types.mdx index 7ef8afd..5679843 100644 --- a/docs/docs/reference/03-types.mdx +++ b/docs/docs/reference/03-types.mdx @@ -20,12 +20,6 @@ description: TrueSheet type reference. | `"${number}%"` | Fixed height in % | **_16+_** | ✅ | | `number` | Fixed height | **_16+_** | ✅ | -:::info -`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. - -Alternatively, you can programmatically call [`resize`](/reference/methods#ref-methods) to adjust the sheet size on-the-fly. -::: - ## `TrueSheetGrabberProps` Grabber props to be used for android grabber or handle. diff --git a/example/src/sheets/PromptSheet.tsx b/example/src/sheets/PromptSheet.tsx index 4e9e8e5..8da13c8 100644 --- a/example/src/sheets/PromptSheet.tsx +++ b/example/src/sheets/PromptSheet.tsx @@ -1,19 +1,11 @@ -import React, { - forwardRef, - useRef, - type Ref, - useImperativeHandle, - useState, - useEffect, -} from 'react' +import React, { forwardRef, useRef, type Ref, useImperativeHandle, useState } from 'react' import { TextInput, View, type TextStyle, type ViewStyle } from 'react-native' -import { TrueSheet, type SheetSize, type TrueSheetProps } from '@lodev09/react-native-true-sheet' +import { TrueSheet, type TrueSheetProps } from '@lodev09/react-native-true-sheet' import { BORDER_RADIUS, DARK, DARK_BLUE, - FOOTER_HEIGHT, GRABBER_COLOR, GRAY, INPUT_HEIGHT, @@ -28,13 +20,10 @@ interface PromptSheetProps extends TrueSheetProps {} export const PromptSheet = forwardRef((props: PromptSheetProps, ref: Ref) => { const sheetRef = useRef(null) - const [contentHeight, setContentHeight] = useState() const [isSubmitted, setIsSubmitted] = useState(false) - const [size, setSize] = useState('auto') const handleDismiss = () => { setIsSubmitted(false) - setSize('auto') console.log('Sheet prompt dismissed!') } @@ -49,17 +38,11 @@ export const PromptSheet = forwardRef((props: PromptSheetProps, ref: Ref(ref, () => sheetRef.current) - useEffect(() => { - if (isSubmitted && contentHeight) { - setSize(contentHeight + FOOTER_HEIGHT) - } - }, [isSubmitted, contentHeight]) - return ( } {...props} > - isSubmitted && setContentHeight(e.nativeEvent.layout.height)}> - - - {isSubmitted && } -