Skip to content

Commit

Permalink
chore(android): basic
Browse files Browse the repository at this point in the history
  • Loading branch information
lodev09 committed Mar 25, 2024
1 parent 2c5b135 commit e7fd5d5
Show file tree
Hide file tree
Showing 11 changed files with 131 additions and 75 deletions.
1 change: 1 addition & 0 deletions NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
- [UISheetPresentationController](https://sarunw.com/posts/bottom-sheet-in-ios-15-with-uisheetpresentationcontroller/#detent)
- [Bottom Sheet (Android)](https://shopify.engineering/creating-native-components-accept-react-native-subviews)
- [BottomSheetBehaviour](https://medium.com/@wind.orca.pe/implementing-a-bottom-sheet-with-multiple-nested-scroll-children-in-android-22361c8223dd)
- [Native View + Module](https://susuthapa19961227.medium.com/bridging-the-gap-how-to-call-native-component-functions-from-reactnative-a8d212588b72)
3 changes: 1 addition & 2 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ dependencies {
//noinspection GradleDynamicVersion
implementation "com.facebook.react:react-native:+"
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "androidx.coordinatorlayout:coordinatorlayout:1.2.0"
implementation 'com.google.android.material:material:1.11.0'
implementation "com.google.android.material:material:1.11.0"
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ import com.facebook.react.uimanager.ViewManager

class TrueSheetPackage : ReactPackage {
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
return listOf(
TrueSheetViewModule(reactContext)
)
return listOf(TrueSheetViewModule(reactContext))
}

override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
Expand Down
36 changes: 20 additions & 16 deletions android/src/main/java/com/lodev09/truesheet/TrueSheetView.kt
Original file line number Diff line number Diff line change
@@ -1,32 +1,36 @@
package com.lodev09.truesheet

import android.annotation.SuppressLint
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.widget.FrameLayout
import android.widget.LinearLayout
import android.widget.RelativeLayout
import com.google.android.material.bottomsheet.BottomSheetBehavior
import androidx.coordinatorlayout.widget.CoordinatorLayout
import com.facebook.react.bridge.ReactContext
import com.google.android.material.bottomsheet.BottomSheetDialog

class TrueSheetView(context: Context): CoordinatorLayout(context) {
class TrueSheetView(context: ReactContext): FrameLayout(context) {

private lateinit var contents: RelativeLayout
private set
private lateinit var behavior: BottomSheetBehavior<*>
private set
private lateinit var contentView: View
private lateinit var bottomSheetDialog: BottomSheetDialog

override fun onViewAdded(child: View?) {
super.onViewAdded(child)
if (child != null) {
removeView(child)
bottomSheetDialog = BottomSheetDialog(context)
bottomSheetDialog.setContentView(child)
}
}

contents = child as RelativeLayout
fun present() {
bottomSheetDialog.show()
}

behavior = BottomSheetBehavior.from(contents).apply {
// virtually disables 'third' breakpoint
halfExpandedRatio = 0.9999999f
isFitToContents = true
isHideable = true
// default to no collapsed state
skipCollapsed = true
setPeekHeight(Integer.MAX_VALUE)
}
fun dismiss() {
bottomSheetDialog.dismiss()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class TrueSheetViewManager : ViewGroupManager<TrueSheetView>() {

@SuppressLint("InflateParams")
override fun createViewInstance(reactContext: ThemedReactContext): TrueSheetView {
return LayoutInflater.from(reactContext).inflate(R.layout.truesheet_layout, null) as TrueSheetView
return TrueSheetView(reactContext)
}

companion object {
Expand Down
44 changes: 44 additions & 0 deletions android/src/main/java/com/lodev09/truesheet/TrueSheetViewModule.kt
Original file line number Diff line number Diff line change
@@ -1,13 +1,57 @@
package com.lodev09.truesheet

import android.util.Log
import com.facebook.react.bridge.Promise
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod
import com.facebook.react.bridge.UiThreadUtil
import com.facebook.react.module.annotations.ReactModule
import com.facebook.react.uimanager.UIManagerHelper
import kotlinx.coroutines.CoroutineScope
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine

@ReactModule(name = TrueSheetViewModule.NAME)
class TrueSheetViewModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
override fun getName(): String = NAME

private fun withTrueSheetView(tag: Int, closure: (trueSheetView: TrueSheetView) -> Unit) {
UiThreadUtil.runOnUiThread {
try {
val manager = UIManagerHelper.getUIManagerForReactTag(reactApplicationContext, tag)
val view = manager?.resolveView(tag)
if (view == null) {
Log.d(NAME, "TrueSheetView with tag $tag not found")
return@runOnUiThread
}

if (view is TrueSheetView) {
closure(view)
} else {
Log.d(NAME, "View is not of type TrueSheetView")
}
} catch (e: Exception) {
e.printStackTrace()
}
}
}

@ReactMethod
fun present(tag: Int, index: Int, promise: Promise) {
withTrueSheetView(tag) { trueSheetView ->
trueSheetView.present()
}
}

@ReactMethod
fun dismiss(tag: Int, promise: Promise) {
withTrueSheetView(tag) { trueSheetView ->
trueSheetView.dismiss()
}
}

companion object {
const val NAME = "TrueSheetView"
}
Expand Down
13 changes: 13 additions & 0 deletions android/src/main/java/com/lodev09/truesheet/utils/withPromise.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.lodev09.truesheet.utils

import com.facebook.react.bridge.Promise

inline fun withPromise(promise: Promise, closure: () -> Any?) {
try {
val result = closure()
promise.resolve(result)
} catch (e: Throwable) {
e.printStackTrace()
promise.reject("Error", e.message, e.cause)
}
}
3 changes: 1 addition & 2 deletions android/src/main/res/layout/truesheet_layout.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
android:id="@+id/contents"
android:layout_gravity="center_horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="com.lodev09.truesheet.TrueSheetBottomSheetBehavior"/>
android:layout_height="match_parent" />

</com.lodev09.truesheet.TrueSheetView>
10 changes: 5 additions & 5 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ export default function App() {
const _scrollViewRef = useRef<ScrollView>(null)
const _flatListRef = useRef<FlatList>(null)

const presentSheet1 = (_index = 0) => {
// sheet1.current?.present(index)
const presentSheet1 = (index = 0) => {
sheet1.current?.present(index)
}

const dismissSheet1 = () => {
// sheet1.current?.dismiss()
sheet1.current?.dismiss()
}

return (
Expand All @@ -67,9 +67,9 @@ export default function App() {
>
<DemoContent color={DARK_GRAY} />
<DemoContent color={DARK_GRAY} />
<Button text="Present Large" onPress={() => presentSheet1(2)} />
{/* <Button text="Present Large" onPress={() => presentSheet1(2)} />
<Button text="Present 80%" onPress={() => presentSheet1(1)} />
<Button text="Present Auto" onPress={() => presentSheet1(0)} />
<Button text="Present Auto" onPress={() => presentSheet1(0)} /> */}
<Button text="Dismis" onPress={dismissSheet1} />
</TrueSheet>

Expand Down
46 changes: 44 additions & 2 deletions src/TrueSheet.android.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
import React, { Component, PureComponent, createRef, type ReactNode, type RefObject } from 'react'
import { requireNativeComponent, Platform, type NativeMethods, View } from 'react-native'
import {
requireNativeComponent,
Platform,
type NativeMethods,
View,
findNodeHandle,
type StyleProp,
type ViewStyle,
} from 'react-native'
import type { TrueSheetProps } from './types'
import { TrueSheetModule } from './TrueSheetModule'

const LINKING_ERROR =
`The package '@lodev09/react-native-true-sheet' doesn't seem to be linked. Make sure: \n\n` +
Expand All @@ -11,6 +20,7 @@ const LINKING_ERROR =
const ComponentName = 'TrueSheetView'

interface TrueSheetNativeViewProps {
style: StyleProp<ViewStyle>
sizes: TrueSheetProps['sizes']
children: ReactNode
}
Expand All @@ -34,13 +44,45 @@ export class TrueSheet extends PureComponent<TrueSheetProps> {
this.ref = createRef<NativeRef>()
}

private get handle(): number {
const nodeHandle = findNodeHandle(this.ref.current)
if (nodeHandle == null || nodeHandle === -1) {
throw new Error(`Could not get native view tag`)
}

return nodeHandle
}

/**
* Present the modal sheet at size index.
* See `sizes` prop
*/
public async present(index: number = 0) {
await TrueSheetModule.present(this.handle, index)
}

public async dismiss() {
await TrueSheetModule.dismiss(this.handle)
}

render(): ReactNode {
return (
<TrueSheetNativeView ref={this.ref} sizes={this.props.sizes ?? ['medium', 'large']}>
<TrueSheetNativeView
style={$nativeSheet}
ref={this.ref}
sizes={this.props.sizes ?? ['medium', 'large']}
>
<View style={{ backgroundColor: this.props.backgroundColor ?? 'white' }}>
<View style={this.props.style}>{this.props.children}</View>
</View>
</TrueSheetNativeView>
)
}
}

const $nativeSheet: ViewStyle = {
backgroundColor: 'red',
position: 'absolute',
left: -9999,
zIndex: -99,
}

0 comments on commit e7fd5d5

Please sign in to comment.