Skip to content

Commit

Permalink
feat: handle auto sizing properly (#9)
Browse files Browse the repository at this point in the history
* feat: handle `auto` sizing properly

* docs: remove `auto` note 🎉
  • Loading branch information
lodev09 authored Apr 22, 2024
1 parent 75b23b0 commit 3988bee
Show file tree
Hide file tree
Showing 9 changed files with 124 additions and 114 deletions.
27 changes: 11 additions & 16 deletions android/src/main/java/com/lodev09/truesheet/TrueSheetDialog.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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<Any> = arrayOf("medium", "large")
Expand Down Expand Up @@ -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()
}
}

Expand All @@ -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)
Expand All @@ -80,7 +81,7 @@ class TrueSheetDialog(private val reactContext: ThemedReactContext, private val

is String -> {
when (size) {
"auto" -> contentHeight
"auto" -> contentHeight + footerHeight

"large" -> maxScreenHeight

Expand Down Expand Up @@ -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
Expand All @@ -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])
}
}
}
Expand Down
37 changes: 18 additions & 19 deletions android/src/main/java/com/lodev09/truesheet/TrueSheetView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down Expand Up @@ -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
}
}
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand All @@ -239,7 +238,7 @@ class TrueSheetView(context: Context) :

fun setSizes(newSizes: Array<Any>) {
sheetDialog.sizes = newSizes
configureIfPresented()
configureIfShowing()
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,16 @@ class TrueSheetViewManager : ViewGroupManager<TrueSheetView>() {
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<Any>()
Expand Down
6 changes: 0 additions & 6 deletions docs/docs/reference/03-types.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
35 changes: 8 additions & 27 deletions example/src/sheets/PromptSheet.tsx
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -28,13 +20,10 @@ interface PromptSheetProps extends TrueSheetProps {}
export const PromptSheet = forwardRef((props: PromptSheetProps, ref: Ref<TrueSheet>) => {
const sheetRef = useRef<TrueSheet>(null)

const [contentHeight, setContentHeight] = useState<number>()
const [isSubmitted, setIsSubmitted] = useState(false)
const [size, setSize] = useState<SheetSize>('auto')

const handleDismiss = () => {
setIsSubmitted(false)
setSize('auto')
console.log('Sheet prompt dismissed!')
}

Expand All @@ -49,17 +38,11 @@ export const PromptSheet = forwardRef((props: PromptSheetProps, ref: Ref<TrueShe

useImperativeHandle<TrueSheet | null, TrueSheet | null>(ref, () => sheetRef.current)

useEffect(() => {
if (isSubmitted && contentHeight) {
setSize(contentHeight + FOOTER_HEIGHT)
}
}, [isSubmitted, contentHeight])

return (
<TrueSheet
ref={sheetRef}
name="prompt-sheet"
sizes={[size, '80%']}
sizes={['auto', 'large']}
contentContainerStyle={$content}
blurTint="dark"
backgroundColor={DARK}
Expand All @@ -73,13 +56,11 @@ export const PromptSheet = forwardRef((props: PromptSheetProps, ref: Ref<TrueShe
FooterComponent={<Footer />}
{...props}
>
<View onLayout={(e) => isSubmitted && setContentHeight(e.nativeEvent.layout.height)}>
<DemoContent color={DARK_BLUE} text={random(RANDOM_TEXTS)} />
<Input />
{isSubmitted && <Input />}
<Button text="Submit" onPress={submit} />
<Button text="Dismis" onPress={dismiss} />
</View>
<DemoContent color={DARK_BLUE} text={random(RANDOM_TEXTS)} />
<Input />
{isSubmitted && <Input />}
<Button text="Submit" onPress={submit} />
<Button text="Dismis" onPress={dismiss} />
</TrueSheet>
)
})
Expand Down
Loading

0 comments on commit 3988bee

Please sign in to comment.