let native scrollview handle layout
This commit is contained in:
@@ -23,6 +23,10 @@ public class BottomSheetModule: Module {
|
|||||||
view.updateLayout()
|
view.updateLayout()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Prop("containerBackgroundColor") { (view: SheetView, prop: UIColor) in
|
||||||
|
view.containerBackgroundColor = prop
|
||||||
|
}
|
||||||
|
|
||||||
Prop("cornerRadius") { (view: SheetView, prop: Float) in
|
Prop("cornerRadius") { (view: SheetView, prop: Float) in
|
||||||
view.cornerRadius = CGFloat(prop)
|
view.cornerRadius = CGFloat(prop)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
//
|
||||||
|
// BottomSheetScrollView.swift
|
||||||
|
// Pods
|
||||||
|
//
|
||||||
|
// Created by Hailey on 10/9/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
class BottomSheetScrollView: UIScrollView, UIScrollViewDelegate {
|
||||||
|
private var previousHeight: CGFloat?
|
||||||
|
|
||||||
|
init() {
|
||||||
|
super.init(frame: .zero)
|
||||||
|
if let window = Util.getWindow() {
|
||||||
|
self.frame = window.bounds
|
||||||
|
self.contentInset = UIEdgeInsets(top: 0,
|
||||||
|
left: 0,
|
||||||
|
bottom: window.safeAreaInsets.bottom,
|
||||||
|
right: 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override func layoutSubviews() {
|
||||||
|
super.layoutSubviews()
|
||||||
|
|
||||||
|
if let height = self.subviews.first?.frame.size.height,
|
||||||
|
self.previousHeight != height,
|
||||||
|
let window = self.window {
|
||||||
|
self.contentSize = CGSize(width: window.bounds.width, height: height + window.safeAreaInsets.bottom)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,9 +5,14 @@ class SheetView: ExpoView, UISheetPresentationControllerDelegate {
|
|||||||
// Views
|
// Views
|
||||||
private var sheetVc: SheetViewController!
|
private var sheetVc: SheetViewController!
|
||||||
private var innerView: UIView?
|
private var innerView: UIView?
|
||||||
|
private var contentHeight: CGFloat? {
|
||||||
|
get {
|
||||||
|
self.innerView?.frame.height
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Scroll view
|
// Scroll view
|
||||||
private var scrollView: RCTScrollView?
|
private var scrollView: BottomSheetScrollView!
|
||||||
|
|
||||||
// Touch handler
|
// Touch handler
|
||||||
private var touchHandler: RCTTouchHandler?
|
private var touchHandler: RCTTouchHandler?
|
||||||
@@ -29,6 +34,11 @@ class SheetView: ExpoView, UISheetPresentationControllerDelegate {
|
|||||||
// React view props
|
// React view props
|
||||||
var preventDismiss = false
|
var preventDismiss = false
|
||||||
var preventExpansion = false
|
var preventExpansion = false
|
||||||
|
var containerBackgroundColor: UIColor? {
|
||||||
|
didSet {
|
||||||
|
self.scrollView.backgroundColor = containerBackgroundColor
|
||||||
|
}
|
||||||
|
}
|
||||||
var cornerRadius: CGFloat?
|
var cornerRadius: CGFloat?
|
||||||
var minHeight = 0.0
|
var minHeight = 0.0
|
||||||
var maxHeight: CGFloat = Util.getScreenHeight() {
|
var maxHeight: CGFloat = Util.getScreenHeight() {
|
||||||
@@ -79,11 +89,16 @@ class SheetView: ExpoView, UISheetPresentationControllerDelegate {
|
|||||||
required init (appContext: AppContext? = nil) {
|
required init (appContext: AppContext? = nil) {
|
||||||
super.init(appContext: appContext)
|
super.init(appContext: appContext)
|
||||||
|
|
||||||
|
self.scrollView = BottomSheetScrollView()
|
||||||
|
|
||||||
self.sheetVc = SheetViewController()
|
self.sheetVc = SheetViewController()
|
||||||
if let sheet = self.sheetVc.sheetPresentationController {
|
if let sheet = self.sheetVc.sheetPresentationController {
|
||||||
sheet.delegate = self
|
sheet.delegate = self
|
||||||
}
|
}
|
||||||
|
self.sheetVc.view.addSubview(self.scrollView)
|
||||||
|
|
||||||
|
self.touchHandler = RCTTouchHandler(bridge: appContext?.reactBridge)
|
||||||
|
|
||||||
SheetManager.shared.add(self)
|
SheetManager.shared.add(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,36 +106,23 @@ class SheetView: ExpoView, UISheetPresentationControllerDelegate {
|
|||||||
self.destroy()
|
self.destroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
// We don't want this view to actually get added to the tree, so we'll simply store it for adding
|
|
||||||
// to the SheetViewController
|
|
||||||
override func insertReactSubview(_ subview: UIView!, at atIndex: Int) {
|
override func insertReactSubview(_ subview: UIView!, at atIndex: Int) {
|
||||||
let touchHandler = RCTTouchHandler(bridge: self.appContext?.reactBridge)
|
self.touchHandler?.attach(to: subview)
|
||||||
touchHandler?.attach(to: subview)
|
self.scrollView.addSubview(subview)
|
||||||
|
|
||||||
self.touchHandler = touchHandler
|
|
||||||
self.innerView = subview
|
self.innerView = subview
|
||||||
|
self.present()
|
||||||
}
|
}
|
||||||
|
|
||||||
// We'll grab the content height from here so we know the initial detent to set
|
|
||||||
override func layoutSubviews() {
|
override func layoutSubviews() {
|
||||||
super.layoutSubviews()
|
super.layoutSubviews()
|
||||||
|
|
||||||
guard let innerView = self.innerView else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if innerView.subviews.count != 1 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
self.present()
|
self.present()
|
||||||
}
|
}
|
||||||
|
|
||||||
private func destroy() {
|
private func destroy() {
|
||||||
self.isClosing = false
|
|
||||||
self.isOpen = false
|
|
||||||
self.touchHandler?.detach(from: self.innerView)
|
self.touchHandler?.detach(from: self.innerView)
|
||||||
self.touchHandler = nil
|
self.touchHandler = nil
|
||||||
|
self.isClosing = false
|
||||||
|
self.isOpen = false
|
||||||
SheetManager.shared.remove(self)
|
SheetManager.shared.remove(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,13 +132,11 @@ class SheetView: ExpoView, UISheetPresentationControllerDelegate {
|
|||||||
guard !self.isOpen,
|
guard !self.isOpen,
|
||||||
!self.isOpening,
|
!self.isOpening,
|
||||||
!self.isClosing,
|
!self.isClosing,
|
||||||
let innerView = self.innerView,
|
let contentHeight = self.contentHeight,
|
||||||
let contentHeight = innerView.subviews.first?.frame.height,
|
|
||||||
let rvc = self.reactViewController() else {
|
let rvc = self.reactViewController() else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
self.sheetVc.view.addSubview(innerView)
|
|
||||||
self.sheetVc.setDetents(contentHeight: self.clampHeight(contentHeight), preventExpansion: self.preventExpansion)
|
self.sheetVc.setDetents(contentHeight: self.clampHeight(contentHeight), preventExpansion: self.preventExpansion)
|
||||||
if let sheet = sheetVc.sheetPresentationController {
|
if let sheet = sheetVc.sheetPresentationController {
|
||||||
sheet.preferredCornerRadius = self.cornerRadius
|
sheet.preferredCornerRadius = self.cornerRadius
|
||||||
@@ -153,7 +153,7 @@ class SheetView: ExpoView, UISheetPresentationControllerDelegate {
|
|||||||
|
|
||||||
func updateLayout() {
|
func updateLayout() {
|
||||||
if self.prevLayoutDetentIdentifier == self.selectedDetentIdentifier,
|
if self.prevLayoutDetentIdentifier == self.selectedDetentIdentifier,
|
||||||
let contentHeight = self.innerView?.subviews.first?.frame.size.height {
|
let contentHeight = self.contentHeight {
|
||||||
self.sheetVc.updateDetents(contentHeight: self.clampHeight(contentHeight),
|
self.sheetVc.updateDetents(contentHeight: self.clampHeight(contentHeight),
|
||||||
preventExpansion: self.preventExpansion)
|
preventExpansion: self.preventExpansion)
|
||||||
self.selectedDetentIdentifier = self.sheetVc.getCurrentDetentIdentifier()
|
self.selectedDetentIdentifier = self.sheetVc.getCurrentDetentIdentifier()
|
||||||
|
|||||||
@@ -6,9 +6,16 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
class Util {
|
class Util {
|
||||||
static func getScreenHeight() -> CGFloat {
|
static func getWindow() -> UIWindow? {
|
||||||
if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
|
if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
|
||||||
let window = windowScene.windows.first {
|
let window = windowScene.windows.first {
|
||||||
|
return window
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
static func getScreenHeight() -> CGFloat {
|
||||||
|
if let window = Self.getWindow() {
|
||||||
let safeAreaInsets = window.safeAreaInsets
|
let safeAreaInsets = window.safeAreaInsets
|
||||||
let fullScreenHeight = UIScreen.main.bounds.height
|
let fullScreenHeight = UIScreen.main.bounds.height
|
||||||
return fullScreenHeight - (safeAreaInsets.top + safeAreaInsets.bottom)
|
return fullScreenHeight - (safeAreaInsets.top + safeAreaInsets.bottom)
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ export class BottomSheetNativeComponent extends React.Component<
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {children, backgroundColor, ...rest} = this.props
|
const {children, ...rest} = this.props
|
||||||
const cornerRadius = rest.cornerRadius ?? 0
|
const cornerRadius = rest.cornerRadius ?? 0
|
||||||
|
|
||||||
if (!this.state.open) {
|
if (!this.state.open) {
|
||||||
@@ -81,23 +81,20 @@ export class BottomSheetNativeComponent extends React.Component<
|
|||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
height: screenHeight,
|
height: screenHeight,
|
||||||
width: '100%',
|
width: '100%',
|
||||||
}}
|
}}>
|
||||||
containerBackgroundColor={backgroundColor}>
|
{/*<View*/}
|
||||||
<View
|
{/* style={[*/}
|
||||||
style={[
|
{/* {*/}
|
||||||
{
|
{/* flex: 1,*/}
|
||||||
flex: 1,
|
{/* backgroundColor,*/}
|
||||||
backgroundColor,
|
{/* },*/}
|
||||||
},
|
{/* Platform.OS === 'android' && {*/}
|
||||||
Platform.OS === 'android' && {
|
{/* borderTopLeftRadius: cornerRadius,*/}
|
||||||
borderTopLeftRadius: cornerRadius,
|
{/* borderTopRightRadius: cornerRadius,*/}
|
||||||
borderTopRightRadius: cornerRadius,
|
{/* },*/}
|
||||||
},
|
{/* ]}>*/}
|
||||||
]}>
|
<BottomSheetPortalProvider>{children}</BottomSheetPortalProvider>
|
||||||
<ScrollView>
|
{/*</View>*/}
|
||||||
<BottomSheetPortalProvider>{children}</BottomSheetPortalProvider>
|
|
||||||
</ScrollView>
|
|
||||||
</View>
|
|
||||||
</NativeView>
|
</NativeView>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import {
|
|||||||
NativeScrollEvent,
|
NativeScrollEvent,
|
||||||
NativeSyntheticEvent,
|
NativeSyntheticEvent,
|
||||||
Pressable,
|
Pressable,
|
||||||
|
processColor,
|
||||||
ScrollView,
|
ScrollView,
|
||||||
StyleProp,
|
StyleProp,
|
||||||
TextInput,
|
TextInput,
|
||||||
@@ -156,11 +157,11 @@ export function Outer({
|
|||||||
<BottomSheet
|
<BottomSheet
|
||||||
ref={ref}
|
ref={ref}
|
||||||
cornerRadius={20}
|
cornerRadius={20}
|
||||||
backgroundColor={t.atoms.bg.backgroundColor}
|
|
||||||
{...nativeOptions}
|
{...nativeOptions}
|
||||||
onSnapPointChange={onSnapPointChange}
|
onSnapPointChange={onSnapPointChange}
|
||||||
onStateChange={onStateChange}
|
onStateChange={onStateChange}
|
||||||
disableDrag={disableDrag}>
|
disableDrag={disableDrag}
|
||||||
|
containerBackgroundColor={processColor(t.atoms.bg.backgroundColor)}>
|
||||||
<Context.Provider value={context}>
|
<Context.Provider value={context}>
|
||||||
<View testID={testID}>{children}</View>
|
<View testID={testID}>{children}</View>
|
||||||
</Context.Provider>
|
</Context.Provider>
|
||||||
@@ -214,6 +215,8 @@ export const ScrollableInner = React.forwardRef<ScrollView, DialogInnerProps>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return children
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<KeyboardAwareScrollView
|
<KeyboardAwareScrollView
|
||||||
style={[style]}
|
style={[style]}
|
||||||
|
|||||||
Reference in New Issue
Block a user