Skip to content

Commit

Permalink
refactor(android): conditional content
Browse files Browse the repository at this point in the history
  • Loading branch information
lodev09 committed Apr 25, 2024
1 parent 678bb84 commit 04e0f52
Show file tree
Hide file tree
Showing 5 changed files with 160 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,28 @@ package com.lodev09.truesheet
import android.graphics.Color
import android.view.ViewGroup
import android.view.WindowManager
import android.widget.FrameLayout
import com.facebook.react.uimanager.ThemedReactContext
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetBehavior.BottomSheetCallback
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.lodev09.truesheet.core.KeyboardManager
import com.lodev09.truesheet.core.RootSheetView
import com.lodev09.truesheet.core.Utils

data class SizeInfo(val index: Int, val value: Float)

class TrueSheetDialog(private val reactContext: ThemedReactContext, private val rootSheetView: RootSheetView) :
BottomSheetDialog(reactContext) {
class TrueSheetContainer(private val reactContext: ThemedReactContext, private val rootSheetView: RootSheetView) {

private var keyboardManager = KeyboardManager(reactContext)
private var sheetDialog: BottomSheetDialog? = null

lateinit var onDismissListener: () -> Unit
lateinit var onShowListener: () -> Unit
lateinit var bottomSheetCallback: (BottomSheetCallback)
lateinit var behavior: BottomSheetBehavior<FrameLayout>

var dimmed = true

var maxScreenHeight: Int = 0
var contentHeight: Int = 0
Expand All @@ -26,39 +35,88 @@ class TrueSheetDialog(private val reactContext: ThemedReactContext, private val

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

private var sheetView: ViewGroup
private var sheetView: ViewGroup? = null

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

// 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
)
val isShowing: Boolean
get() = when (dimmed) {
true -> sheetDialog?.isShowing == true
else -> TODO()
}

init {
// Update the usable sheet height
maxScreenHeight = Utils.screenHeight(reactContext)
}

fun setup() {
if (dimmed) {
sheetDialog = BottomSheetDialog(reactContext)
sheetDialog?.let {
it.setContentView(rootSheetView)

it.setOnShowListener {
onShowListener()
}

it.setOnDismissListener {
onDismissListener()
}

sheetView = rootSheetView.parent as ViewGroup
sheetView?.setBackgroundColor(Color.TRANSPARENT)

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

behavior = it.behavior
}
} else {
TODO()
}

behavior.addBottomSheetCallback(bottomSheetCallback)
}

fun show(sizeIndex: Int) {
if (isShowing) {
setStateForSizeIndex(sizeIndex)
} else {
configure()
setStateForSizeIndex(sizeIndex)

this.show()
when (dimmed) {
true -> sheetDialog?.show()
else -> TODO()
}
}
}

fun dismiss() {
when (dimmed) {
true -> sheetDialog?.dismiss()
else -> TODO()
}
}

fun positionFooter() {
footerView?.apply {
y = (maxScreenHeight - sheetView.top - footerHeight).toFloat()
y = (maxScreenHeight - (sheetView?.top ?: 0) - footerHeight).toFloat()
}
}

fun setDismissible(dismissible: Boolean) {
when (dimmed) {
true -> {
behavior.isHideable = dismissible
sheetDialog?.setCancelable(dismissible)
}

else -> TODO()
}
}

Expand Down Expand Up @@ -207,40 +265,43 @@ class TrueSheetDialog(private val reactContext: ThemedReactContext, private val
/**
* Get the SizeInfo data by state.
*/
fun getSizeInfoForState(state: Int): SizeInfo? =
when (sizes.size) {
1 -> {
when (state) {
BottomSheetBehavior.STATE_EXPANDED -> SizeInfo(0, Utils.toDIP(behavior.maxHeight))
else -> null
fun getSizeInfoForState(state: Int): SizeInfo? {
behavior.apply {
return when (sizes.size) {
1 -> {
when (state) {
BottomSheetBehavior.STATE_EXPANDED -> SizeInfo(0, Utils.toDIP(maxHeight))
else -> null
}
}
}

2 -> {
when (state) {
BottomSheetBehavior.STATE_COLLAPSED -> SizeInfo(0, Utils.toDIP(behavior.peekHeight))
BottomSheetBehavior.STATE_EXPANDED -> SizeInfo(1, Utils.toDIP(behavior.maxHeight))
else -> null
2 -> {
when (state) {
BottomSheetBehavior.STATE_COLLAPSED -> SizeInfo(0, Utils.toDIP(peekHeight))
BottomSheetBehavior.STATE_EXPANDED -> SizeInfo(1, Utils.toDIP(maxHeight))
else -> null
}
}
}

3 -> {
when (state) {
BottomSheetBehavior.STATE_COLLAPSED -> SizeInfo(0, Utils.toDIP(behavior.peekHeight))
3 -> {
when (state) {
BottomSheetBehavior.STATE_COLLAPSED -> SizeInfo(0, Utils.toDIP(peekHeight))

BottomSheetBehavior.STATE_HALF_EXPANDED -> {
val height = behavior.halfExpandedRatio * maxScreenHeight
SizeInfo(1, Utils.toDIP(height.toInt()))
}
BottomSheetBehavior.STATE_HALF_EXPANDED -> {
val height = halfExpandedRatio * maxScreenHeight
SizeInfo(1, Utils.toDIP(height.toInt()))
}

BottomSheetBehavior.STATE_EXPANDED -> SizeInfo(2, Utils.toDIP(behavior.maxHeight))
BottomSheetBehavior.STATE_EXPANDED -> SizeInfo(2, Utils.toDIP(maxHeight))

else -> null
else -> null
}
}
}

else -> null
else -> null
}
}
}

/**
* Get SizeInfo data for given size index.
Expand Down
95 changes: 51 additions & 44 deletions android/src/main/java/com/lodev09/truesheet/TrueSheetView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class TrueSheetView(context: Context) :
/**
* The main BottomSheetDialog instance.
*/
private val sheetDialog: TrueSheetDialog
private val sheetContainer: TrueSheetContainer

/**
* React root view placeholder.
Expand All @@ -64,12 +64,12 @@ class TrueSheetView(context: Context) :
rootSheetView = RootSheetView(context)
rootSheetView.eventDispatcher = eventDispatcher

sheetDialog = TrueSheetDialog(reactContext, rootSheetView)
sheetContainer = TrueSheetContainer(reactContext, rootSheetView)

// Configure Sheet Dialog
sheetDialog.apply {
sheetContainer.apply {
// Setup listener when the dialog has been presented.
setOnShowListener {
onShowListener = {
registerKeyboardManager()

// Initialize footer y
Expand All @@ -83,11 +83,11 @@ class TrueSheetView(context: Context) :
}

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

// Setup listener when the dialog has been dismissed.
setOnDismissListener {
onDismissListener = {
unregisterKeyboardManager()

dismissPromise?.let { promise ->
Expand All @@ -100,36 +100,37 @@ class TrueSheetView(context: Context) :
}

// Configure sheet behavior events
behavior.addBottomSheetCallback(
object : BottomSheetBehavior.BottomSheetCallback() {
override fun onSlide(sheetView: View, slideOffset: Float) {
footerView?.let {
val y = (maxScreenHeight - sheetView.top - footerHeight).toFloat()
if (slideOffset >= 0) {
it.y = y
} else {
it.y = y - footerHeight * slideOffset
}
bottomSheetCallback = object : BottomSheetBehavior.BottomSheetCallback() {
override fun onSlide(sheetView: View, slideOffset: Float) {
footerView?.let {
val y = (maxScreenHeight - sheetView.top - footerHeight).toFloat()
if (slideOffset >= 0) {
it.y = y
} else {
it.y = y - footerHeight * slideOffset
}
}
}

override fun onStateChanged(view: View, newState: Int) {
val sizeInfo = getSizeInfoForState(newState)
if (sizeInfo != null && sizeInfo.index != activeIndex) {
// Invoke promise when sheet resized programmatically
presentPromise?.let { promise ->
promise()
presentPromise = null
}
override fun onStateChanged(view: View, newState: Int) {
val sizeInfo = getSizeInfoForState(newState)
if (sizeInfo != null && sizeInfo.index != activeIndex) {
// Invoke promise when sheet resized programmatically
presentPromise?.let { promise ->
promise()
presentPromise = null
}

activeIndex = sizeInfo.index
activeIndex = sizeInfo.index

// dispatch onSizeChange event
eventDispatcher?.dispatchEvent(SizeChangeEvent(surfaceId, id, sizeInfo))
}
// dispatch onSizeChange event
eventDispatcher?.dispatchEvent(SizeChangeEvent(surfaceId, id, sizeInfo))
}
}
)
}

// Finally setup content
setup()
}
}

Expand All @@ -149,7 +150,7 @@ class TrueSheetView(context: Context) :

override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
sheetDialog.dismiss()
sheetContainer.dismiss()
}

override fun addView(child: View, index: Int) {
Expand All @@ -160,7 +161,7 @@ class TrueSheetView(context: Context) :
// Container View's first child is the Content View
footerView = it.getChildAt(1) as ViewGroup

sheetDialog.footerView = footerView
sheetContainer.footerView = footerView

// rootView's first child is the Container View
rootSheetView.addView(it, index)
Expand Down Expand Up @@ -206,59 +207,65 @@ class TrueSheetView(context: Context) :
override fun onHostDestroy() {
// Drop the instance if the host is destroyed which will dismiss the dialog
reactContext.removeLifecycleEventListener(this)
sheetDialog.dismiss()
sheetContainer.dismiss()
}

private fun configureIfShowing() {
if (sheetDialog.isShowing) {
sheetDialog.configure()
sheetDialog.positionFooter()
if (sheetContainer.isShowing) {
sheetContainer.configure()
sheetContainer.positionFooter()
}
}

fun setMaxHeight(height: Int) {
sheetDialog.maxSheetHeight = height
sheetContainer.maxSheetHeight = height
configureIfShowing()
}

fun setContentHeight(height: Int) {
sheetDialog.contentHeight = height
sheetContainer.contentHeight = height
configureIfShowing()
}

fun setFooterHeight(height: Int) {
sheetDialog.footerHeight = height
sheetContainer.footerHeight = height
configureIfShowing()
}

fun setDismissible(dismissible: Boolean) {
sheetDialog.behavior.isHideable = dismissible
sheetDialog.setCancelable(dismissible)
sheetContainer.setDismissible(dismissible)
}

fun setDimmed(dimmed: Boolean) {
if (sheetContainer.dimmed != dimmed) {
sheetContainer.dimmed = dimmed
sheetContainer.setup()
}
}

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

/**
* Present the sheet at given size index.
*/
fun present(sizeIndex: Int, promiseCallback: () -> Unit) {
if (!sheetDialog.isShowing) {
if (!sheetContainer.isShowing) {
activeIndex = sizeIndex
}

presentPromise = promiseCallback
sheetDialog.show(sizeIndex)
sheetContainer.show(sizeIndex)
}

/**
* Dismisses the sheet.
*/
fun dismiss(promiseCallback: () -> Unit) {
dismissPromise = promiseCallback
sheetDialog.dismiss()
sheetContainer.dismiss()
}

companion object {
Expand Down
Loading

0 comments on commit 04e0f52

Please sign in to comment.