let native scrollview handle layout

This commit is contained in:
Hailey
2024-10-09 21:37:19 -07:00
parent 359ead3ef9
commit ad896cb8dd
6 changed files with 91 additions and 45 deletions
@@ -23,6 +23,10 @@ public class BottomSheetModule: Module {
view.updateLayout()
}
Prop("containerBackgroundColor") { (view: SheetView, prop: UIColor) in
view.containerBackgroundColor = prop
}
Prop("cornerRadius") { (view: SheetView, prop: Float) in
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)
}
}
}
+23 -23
View File
@@ -5,9 +5,14 @@ class SheetView: ExpoView, UISheetPresentationControllerDelegate {
// Views
private var sheetVc: SheetViewController!
private var innerView: UIView?
private var contentHeight: CGFloat? {
get {
self.innerView?.frame.height
}
}
// Scroll view
private var scrollView: RCTScrollView?
private var scrollView: BottomSheetScrollView!
// Touch handler
private var touchHandler: RCTTouchHandler?
@@ -29,6 +34,11 @@ class SheetView: ExpoView, UISheetPresentationControllerDelegate {
// React view props
var preventDismiss = false
var preventExpansion = false
var containerBackgroundColor: UIColor? {
didSet {
self.scrollView.backgroundColor = containerBackgroundColor
}
}
var cornerRadius: CGFloat?
var minHeight = 0.0
var maxHeight: CGFloat = Util.getScreenHeight() {
@@ -79,11 +89,16 @@ class SheetView: ExpoView, UISheetPresentationControllerDelegate {
required init (appContext: AppContext? = nil) {
super.init(appContext: appContext)
self.scrollView = BottomSheetScrollView()
self.sheetVc = SheetViewController()
if let sheet = self.sheetVc.sheetPresentationController {
sheet.delegate = self
}
self.sheetVc.view.addSubview(self.scrollView)
self.touchHandler = RCTTouchHandler(bridge: appContext?.reactBridge)
SheetManager.shared.add(self)
}
@@ -91,36 +106,23 @@ class SheetView: ExpoView, UISheetPresentationControllerDelegate {
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) {
let touchHandler = RCTTouchHandler(bridge: self.appContext?.reactBridge)
touchHandler?.attach(to: subview)
self.touchHandler = touchHandler
self.touchHandler?.attach(to: subview)
self.scrollView.addSubview(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() {
super.layoutSubviews()
guard let innerView = self.innerView else {
return
}
if innerView.subviews.count != 1 {
return
}
self.present()
}
private func destroy() {
self.isClosing = false
self.isOpen = false
self.touchHandler?.detach(from: self.innerView)
self.touchHandler = nil
self.isClosing = false
self.isOpen = false
SheetManager.shared.remove(self)
}
@@ -130,13 +132,11 @@ class SheetView: ExpoView, UISheetPresentationControllerDelegate {
guard !self.isOpen,
!self.isOpening,
!self.isClosing,
let innerView = self.innerView,
let contentHeight = innerView.subviews.first?.frame.height,
let contentHeight = self.contentHeight,
let rvc = self.reactViewController() else {
return
}
self.sheetVc.view.addSubview(innerView)
self.sheetVc.setDetents(contentHeight: self.clampHeight(contentHeight), preventExpansion: self.preventExpansion)
if let sheet = sheetVc.sheetPresentationController {
sheet.preferredCornerRadius = self.cornerRadius
@@ -153,7 +153,7 @@ class SheetView: ExpoView, UISheetPresentationControllerDelegate {
func updateLayout() {
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),
preventExpansion: self.preventExpansion)
self.selectedDetentIdentifier = self.sheetVc.getCurrentDetentIdentifier()
+9 -2
View File
@@ -6,9 +6,16 @@
//
class Util {
static func getScreenHeight() -> CGFloat {
static func getWindow() -> UIWindow? {
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 fullScreenHeight = UIScreen.main.bounds.height
return fullScreenHeight - (safeAreaInsets.top + safeAreaInsets.bottom)
@@ -65,7 +65,7 @@ export class BottomSheetNativeComponent extends React.Component<
}
render() {
const {children, backgroundColor, ...rest} = this.props
const {children, ...rest} = this.props
const cornerRadius = rest.cornerRadius ?? 0
if (!this.state.open) {
@@ -81,23 +81,20 @@ export class BottomSheetNativeComponent extends React.Component<
position: 'absolute',
height: screenHeight,
width: '100%',
}}
containerBackgroundColor={backgroundColor}>
<View
style={[
{
flex: 1,
backgroundColor,
},
Platform.OS === 'android' && {
borderTopLeftRadius: cornerRadius,
borderTopRightRadius: cornerRadius,
},
]}>
<ScrollView>
<BottomSheetPortalProvider>{children}</BottomSheetPortalProvider>
</ScrollView>
</View>
}}>
{/*<View*/}
{/* style={[*/}
{/* {*/}
{/* flex: 1,*/}
{/* backgroundColor,*/}
{/* },*/}
{/* Platform.OS === 'android' && {*/}
{/* borderTopLeftRadius: cornerRadius,*/}
{/* borderTopRightRadius: cornerRadius,*/}
{/* },*/}
{/* ]}>*/}
<BottomSheetPortalProvider>{children}</BottomSheetPortalProvider>
{/*</View>*/}
</NativeView>
)
}
+5 -2
View File
@@ -3,6 +3,7 @@ import {
NativeScrollEvent,
NativeSyntheticEvent,
Pressable,
processColor,
ScrollView,
StyleProp,
TextInput,
@@ -156,11 +157,11 @@ export function Outer({
<BottomSheet
ref={ref}
cornerRadius={20}
backgroundColor={t.atoms.bg.backgroundColor}
{...nativeOptions}
onSnapPointChange={onSnapPointChange}
onStateChange={onStateChange}
disableDrag={disableDrag}>
disableDrag={disableDrag}
containerBackgroundColor={processColor(t.atoms.bg.backgroundColor)}>
<Context.Provider value={context}>
<View testID={testID}>{children}</View>
</Context.Provider>
@@ -214,6 +215,8 @@ export const ScrollableInner = React.forwardRef<ScrollView, DialogInnerProps>(
}
}
return children
return (
<KeyboardAwareScrollView
style={[style]}