Skip to content

Commit

Permalink
feat: add initialIndex & onMount props (#30)
Browse files Browse the repository at this point in the history
* chore: upgrade deps

* refactor: rename types file

* feat(ios): add `initialIndex` prop

* feat(ios): add `onLoad`

* feat: add maps demo

* docs: update docs

* chore: upgrade docs

* feat(android): implement `initialIndex` & `onLoad`

* refactor: rename to `onReady`

* fix: fix size change issue

* refactor: rename event

* feat(ios): add `animateOnMount`

* feat(android): implement `initialIndexAnimated`

* chore: example deps

* refactor: files

* chore: example deps

* docs: add `initialIndexAnimated` prop doc

* docs: preview
  • Loading branch information
lodev09 authored Jun 10, 2024
1 parent d30b873 commit 28d2c18
Show file tree
Hide file tree
Showing 33 changed files with 1,181 additions and 553 deletions.
3 changes: 1 addition & 2 deletions .yarnrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,4 @@ nmHoistingLimits: workspaces
nodeLinker: node-modules

plugins:
spec: "@yarnpkg/plugin-interactive-tools"
spec: "@yarnpkg/plugin-workspace-tools"
spec: "@yarnpkg/plugin-workspace-tools"
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@

The true native bottom sheet experience for your React Native Apps. 💩

<img alt="React Native True Sheet" src="docs/static/img/preview.gif" width="600px" />
<img alt="React Native True Sheet - IOS" src="docs/static/img/preview.gif" width="300" height="600" />
<img alt="React Native True Sheet - Android" src="docs/static/img/preview-2.gif" width="300" height="600" />

## Features

Expand Down
38 changes: 27 additions & 11 deletions android/src/main/java/com/lodev09/truesheet/TrueSheetDialog.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ class TrueSheetDialog(private val reactContext: ThemedReactContext, private val
BottomSheetDialog(reactContext) {

private var keyboardManager = KeyboardManager(reactContext)
private var sheetView: ViewGroup
private var windowAnimation: Int = 0

/**
* Specify whether the sheet background is dimmed.
Expand Down Expand Up @@ -53,19 +55,20 @@ class TrueSheetDialog(private val reactContext: ThemedReactContext, private val

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

private var sheetView: ViewGroup

init {
setContentView(rootSheetView)
sheetView = rootSheetView.parent as ViewGroup
sheetView.setBackgroundColor(Color.TRANSPARENT)

// Setup window params to adjust layout based on Keyboard state.
// Setup window params to adjust layout based on Keyboard state
window?.apply {
// SOFT_INPUT_ADJUST_RESIZE to resize the sheet above the keyboard
setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
)

// Store current windowAnimation value to toggle later
windowAnimation = attributes.windowAnimations
}

// Update the usable sheet height
Expand Down Expand Up @@ -107,18 +110,29 @@ class TrueSheetDialog(private val reactContext: ThemedReactContext, private val
}
}

fun resetAnimation() {
window?.apply {
setWindowAnimations(windowAnimation)
}
}

/**
* Present the sheet.
*/
fun present(sizeIndex: Int) {
fun present(sizeIndex: Int, animated: Boolean = true) {
setupDimmedBackground(sizeIndex)
if (isShowing) {
setStateForSizeIndex(sizeIndex)
} else {
configure()
setStateForSizeIndex(sizeIndex)

this.show()
if (!animated) {
// Disable animation
window?.setWindowAnimations(0)
}

show()
}
}

Expand Down Expand Up @@ -178,10 +192,7 @@ class TrueSheetDialog(private val reactContext: ThemedReactContext, private val
else -> (maxScreenHeight * 0.5).toInt()
}

return when (maxSheetHeight) {
null -> height
else -> minOf(height, maxSheetHeight ?: maxScreenHeight)
}
return maxSheetHeight?.let { minOf(height, it, maxScreenHeight) } ?: minOf(height, maxScreenHeight)
}

/**
Expand Down Expand Up @@ -216,7 +227,7 @@ class TrueSheetDialog(private val reactContext: ThemedReactContext, private val
* Also update footer's Y position.
*/
fun registerKeyboardManager() {
keyboardManager.registerKeyboardListener(object : KeyboardManager.OnKeyboardListener {
keyboardManager.registerKeyboardListener(object : KeyboardManager.OnKeyboardChangeListener {
override fun onKeyboardStateChange(isVisible: Boolean, visibleHeight: Int?) {
maxScreenHeight = when (isVisible) {
true -> visibleHeight ?: 0
Expand All @@ -228,6 +239,10 @@ class TrueSheetDialog(private val reactContext: ThemedReactContext, private val
})
}

fun setOnSizeChangeListener(listener: RootSheetView.OnSizeChangeListener) {
rootSheetView.setOnSizeChangeListener(listener)
}

/**
* Remove keyboard listener.
*/
Expand Down Expand Up @@ -263,7 +278,8 @@ class TrueSheetDialog(private val reactContext: ThemedReactContext, private val
isFitToContents = false

setPeekHeight(getSizeHeight(sizes[0]), isShowing)
halfExpandedRatio = getSizeHeight(sizes[1]).toFloat() / maxScreenHeight.toFloat()

halfExpandedRatio = minOf(getSizeHeight(sizes[1]).toFloat() / maxScreenHeight.toFloat(), 1.0f)
maxHeight = getSizeHeight(sizes[2])
}
}
Expand Down
66 changes: 50 additions & 16 deletions android/src/main/java/com/lodev09/truesheet/TrueSheetView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ import com.facebook.react.uimanager.ThemedReactContext
import com.facebook.react.uimanager.UIManagerHelper
import com.facebook.react.uimanager.events.EventDispatcher
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.lodev09.truesheet.core.DismissEvent
import com.lodev09.truesheet.core.PresentEvent
import com.lodev09.truesheet.core.RootSheetView
import com.lodev09.truesheet.core.SizeChangeEvent
import com.lodev09.truesheet.events.DismissEvent
import com.lodev09.truesheet.events.MountEvent
import com.lodev09.truesheet.events.PresentEvent
import com.lodev09.truesheet.events.SizeChangeEvent

class TrueSheetView(context: Context) :
ViewGroup(context),
Expand All @@ -27,6 +28,9 @@ class TrueSheetView(context: Context) :
private val surfaceId: Int
get() = UIManagerHelper.getSurfaceId(this)

var initialIndex: Int = -1
var initialIndexAnimated: Boolean = true

/**
* Current activeIndex.
*/
Expand All @@ -52,11 +56,6 @@ class TrueSheetView(context: Context) :
*/
private val rootSheetView: RootSheetView

/**
* 2nd child of the container view.
*/
private var footerView: ViewGroup? = null

init {
reactContext.addLifecycleEventListener(this)
eventDispatcher = UIManagerHelper.getEventDispatcherForReactTag(reactContext, id)
Expand All @@ -77,13 +76,16 @@ class TrueSheetView(context: Context) :
positionFooter()
}

// Re-enable animation
resetAnimation()

// Resolve the present promise
presentPromise?.let { promise ->
promise()
presentPromise = null
}

// dispatch onPresent event
// Dispatch onPresent event
eventDispatcher?.dispatchEvent(PresentEvent(surfaceId, id, sheetDialog.getSizeInfoForIndex(currentSizeIndex)))
}

Expand All @@ -97,10 +99,17 @@ class TrueSheetView(context: Context) :
dismissPromise = null
}

// dispatch onDismiss event
// Dispatch onDismiss event
eventDispatcher?.dispatchEvent(DismissEvent(surfaceId, id))
}

// Configure when showing and size changed
setOnSizeChangeListener(object : RootSheetView.OnSizeChangeListener {
override fun onSizeChange(width: Int, height: Int) {
maxScreenHeight = height
}
})

// Configure sheet behavior events
behavior.addBottomSheetCallback(
object : BottomSheetBehavior.BottomSheetCallback() {
Expand Down Expand Up @@ -132,7 +141,7 @@ class TrueSheetView(context: Context) :
currentSizeIndex = sizeInfo.index
setupDimmedBackground(sizeInfo.index)

// dispatch onSizeChange event
// Dispatch onSizeChange event
eventDispatcher?.dispatchEvent(SizeChangeEvent(surfaceId, id, sizeInfo))
}
}
Expand Down Expand Up @@ -164,13 +173,28 @@ class TrueSheetView(context: Context) :
visibility = GONE

(child as ViewGroup).let {
// Container View's first child is the Content View
footerView = it.getChildAt(1) as ViewGroup

sheetDialog.footerView = footerView

// rootView's first child is the Container View
rootSheetView.addView(it, index)

// Initialize content
UiThreadUtil.runOnUiThread {
// 1st child is the content view
val contentView = it.getChildAt(0) as ViewGroup
setContentHeight(contentView.height)

// 2nd child is the footer view
val footerView = it.getChildAt(1) as ViewGroup
sheetDialog.footerView = footerView
setFooterHeight(footerView.height)

if (initialIndex >= 0) {
currentSizeIndex = initialIndex
sheetDialog.present(initialIndex, initialIndexAnimated)
}

// Dispatch onMount event
eventDispatcher?.dispatchEvent(MountEvent(surfaceId, id))
}
}
}

Expand Down Expand Up @@ -224,28 +248,38 @@ class TrueSheetView(context: Context) :
}

fun setMaxHeight(height: Int) {
if (sheetDialog.maxSheetHeight == height) return

sheetDialog.maxSheetHeight = height
configureIfShowing()
}

fun setContentHeight(height: Int) {
if (sheetDialog.contentHeight == height) return

sheetDialog.contentHeight = height
configureIfShowing()
}

fun setFooterHeight(height: Int) {
if (sheetDialog.footerHeight == height) return

sheetDialog.footerHeight = height
configureIfShowing()
}

fun setDimmed(dimmed: Boolean) {
if (sheetDialog.dimmed == dimmed) return

sheetDialog.dimmed = dimmed
if (sheetDialog.isShowing) {
sheetDialog.setupDimmedBackground(currentSizeIndex)
}
}

fun setDimmedIndex(index: Int) {
if (sheetDialog.dimmedIndex == index) return

sheetDialog.dimmedIndex = index
if (sheetDialog.isShowing) {
sheetDialog.setupDimmedBackground(currentSizeIndex)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ import com.facebook.react.common.MapBuilder
import com.facebook.react.uimanager.ThemedReactContext
import com.facebook.react.uimanager.ViewGroupManager
import com.facebook.react.uimanager.annotations.ReactProp
import com.lodev09.truesheet.core.DismissEvent
import com.lodev09.truesheet.core.PresentEvent
import com.lodev09.truesheet.core.SizeChangeEvent
import com.lodev09.truesheet.core.Utils
import com.lodev09.truesheet.events.DismissEvent
import com.lodev09.truesheet.events.MountEvent
import com.lodev09.truesheet.events.PresentEvent
import com.lodev09.truesheet.events.SizeChangeEvent

class TrueSheetViewManager : ViewGroupManager<TrueSheetView>() {
override fun getName() = TAG
Expand All @@ -24,6 +25,7 @@ class TrueSheetViewManager : ViewGroupManager<TrueSheetView>() {

override fun getExportedCustomDirectEventTypeConstants(): MutableMap<String, Any>? =
MapBuilder.builder<String, Any>()
.put(MountEvent.EVENT_NAME, MapBuilder.of("registrationName", "onMount"))
.put(PresentEvent.EVENT_NAME, MapBuilder.of("registrationName", "onPresent"))
.put(DismissEvent.EVENT_NAME, MapBuilder.of("registrationName", "onDismiss"))
.put(SizeChangeEvent.EVENT_NAME, MapBuilder.of("registrationName", "onSizeChange"))
Expand All @@ -44,6 +46,16 @@ class TrueSheetViewManager : ViewGroupManager<TrueSheetView>() {
view.setDimmed(dimmed)
}

@ReactProp(name = "initialIndex")
fun setInitialIndex(view: TrueSheetView, index: Int) {
view.initialIndex = index
}

@ReactProp(name = "initialIndexAnimated")
fun setInitialIndexAnimated(view: TrueSheetView, animate: Boolean) {
view.initialIndexAnimated = animate
}

@ReactProp(name = "dimmedIndex")
fun setDimmedIndex(view: TrueSheetView, index: Int) {
view.setDimmedIndex(index)
Expand Down
51 changes: 0 additions & 51 deletions android/src/main/java/com/lodev09/truesheet/core/Events.kt

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import android.view.inputmethod.InputMethodManager
import com.facebook.react.bridge.ReactContext

class KeyboardManager(reactContext: ReactContext) {
interface OnKeyboardListener {
interface OnKeyboardChangeListener {
fun onKeyboardStateChange(isVisible: Boolean, visibleHeight: Int?)
}

Expand All @@ -20,7 +20,7 @@ class KeyboardManager(reactContext: ReactContext) {
contentView = activity?.findViewById(android.R.id.content)
}

fun registerKeyboardListener(listener: OnKeyboardListener?) {
fun registerKeyboardListener(listener: OnKeyboardChangeListener?) {
contentView?.apply {
unregisterKeyboardListener()

Expand Down
Loading

0 comments on commit 28d2c18

Please sign in to comment.