Hi. Great component! This is working fantastic so far. One thing I haven't figure out is a way to easily dismiss it when tapping outside of the sheet. I can easily dismiss it programmatically by using snapTo(index) however when the sheet is raised I am not sure how to intercept these taps to prevent it from tapping on content underneath.
Thank you!
Put a TouchableWithoutFeedback underneath where you can add a onPress listener to dismiss.
Good suggestion @satya164 ! I can't seem to get it to trigger however. Each time I tap on the content in the background it routes to the item details. Here's my structure:
<View>
<BottomSheet
ref={this.bottomSheet}
snapPoints={[500, 250, 0]}
renderContent={this.renderInner}
renderHeader={this.renderHeader}
initialSnap={2}
callbackNode={this.fall}
enabledInnerScrolling={false}
/>
<TouchableWithoutFeedback
onPress={() => {
console.log('pressed')
this.bottomSheet.current.snapTo(1)
}}
>
<View style={{
backgroundColor: '#2c2c2f',
}}>
<Animated.ScrollView>
... list items that navigate to item details
</Animated.ScrollView
</View>
</TouchableWithoutFeedback>
</View>
It needs to be positioned absolutely above your content, not wrap the content if I understand your code
Not sure I follow. I have a View (root component) with a BottomSheet and a ScrollView wrapped in a TouchableWithoutFeedback per (I thought) your suggestion. TouchableWithoutFeedback requires at least one child component.
Wrapping doesn't work, because then your scrollview handles touches. You want the touchable to be positioned absolutely over your scrollview so it doesn't let any touches go through.
TouchableWithoutFeedbackrequires at least one child component.
You can use an empty view
It's possible to close the bottom sheet by swiping down so in this case the TouchableWithoutFeedback will stay visible and the first tap will try to close already closed sheet. There must be some kind of "closed" event to implement this properly.
I do like this:
import React, { useRef, useEffect } from 'react'
import PropTypes from 'prop-types'
import { View, TouchableWithoutFeedback } from 'react-native'
import BottomSheet from 'reanimated-bottom-sheet'
import Animated from 'react-native-reanimated'
import { useNavigation } from 'hooks'
const { Value, onChange, call, cond, eq, abs, sub, min } = Animated
const Modal = ({ children, snapPoints = [400, 0], initialSnap = null }) => {
const sheet = useRef(null)
const { closeModal } = useNavigation()
const position = new Value(1)
const opacity = min(abs(sub(position, 1)), 0.8)
const zeroIndex = snapPoints.length - 1
const height = snapPoints[0]
const handleOutsidePress = () => {
sheet.current.snapTo(zeroIndex)
}
useEffect(() => {
if (sheet.current) {
sheet.current.snapTo(initialSnap || 0)
}
}, [])
return (
<View style={{ flex: 1 }}>
<TouchableWithoutFeedback onPress={handleOutsidePress}>
<Animated.View
style={{
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
flex: 1,
backgroundColor: '#000',
opacity,
}}
/>
</TouchableWithoutFeedback>
<Animated.Code exec={onChange(position, [cond(eq(position, 1), call([], closeModal))])} />
<BottomSheet
ref={sheet}
initialSnap={zeroIndex}
snapPoints={snapPoints}
callbackNode={position}
renderHeader={() => (
<View
style={{
backgroundColor: 'rgba(255,255,255,0.5)',
width: 50,
height: 3,
margin: 10,
alignSelf: 'center',
borderRadius: 3,
}}
/>
)}
renderContent={() => (
<View
style={{
backgroundColor: '#fff',
padding: 20,
height,
}}
>
{children}
</View>
)}
/>
</View>
)
}
Modal.propTypes = {
children: PropTypes.any,
snapPoints: PropTypes.array,
initialSnap: PropTypes.number,
}
export default Modal
Usage:
const SomeModal = () => {
return (
<Modal snapPoints={[500, 0]}>
<Text>My modal</Text>
</Modal>
)
}
Works like a charm :)
@lindesvard could you please explain about import { useNavigation } from 'hooks' and closeModal?
Is the hooks from this package here?
If you could provide some resources or information I can look at, that would be so helpful. Thanks
I do like this:
import React, { useRef, useEffect } from 'react' import PropTypes from 'prop-types' import { View, TouchableWithoutFeedback } from 'react-native' import BottomSheet from 'reanimated-bottom-sheet' import Animated from 'react-native-reanimated' import { useNavigation } from 'hooks' const { Value, onChange, call, cond, eq, abs, sub, min } = Animated const Modal = ({ children, snapPoints = [400, 0], initialSnap = null }) => { const sheet = useRef(null) const { closeModal } = useNavigation() const position = new Value(1) const opacity = min(abs(sub(position, 1)), 0.8) const zeroIndex = snapPoints.length - 1 const height = snapPoints[0] const handleOutsidePress = () => { sheet.current.snapTo(zeroIndex) } useEffect(() => { if (sheet.current) { sheet.current.snapTo(initialSnap || 0) } }, []) return ( <View style={{ flex: 1 }}> <TouchableWithoutFeedback onPress={handleOutsidePress}> <Animated.View style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, flex: 1, backgroundColor: '#000', opacity, }} /> </TouchableWithoutFeedback> <Animated.Code exec={onChange(position, [cond(eq(position, 1), call([], closeModal))])} /> <BottomSheet ref={sheet} initialSnap={zeroIndex} snapPoints={snapPoints} callbackNode={position} renderHeader={() => ( <View style={{ backgroundColor: 'rgba(255,255,255,0.5)', width: 50, height: 3, margin: 10, alignSelf: 'center', borderRadius: 3, }} /> )} renderContent={() => ( <View style={{ backgroundColor: '#fff', padding: 20, height, }} > {children} </View> )} /> </View> ) } Modal.propTypes = { children: PropTypes.any, snapPoints: PropTypes.array, initialSnap: PropTypes.number, } export default ModalUsage:
const SomeModal = () => { return ( <Modal snapPoints={[500, 0]}> <Text>My modal</Text> </Modal> ) }Works like a charm :)
using this code, scrollview outside <View style={{ flex: 1 }}> cannot be scrolled
@lindesvard
Are you using this https://reactnavigation.org/docs/en/next/use-navigation.html ?
I do like this:
import React, { useRef, useEffect } from 'react' import PropTypes from 'prop-types' import { View, TouchableWithoutFeedback } from 'react-native' import BottomSheet from 'reanimated-bottom-sheet' import Animated from 'react-native-reanimated' import { useNavigation } from 'hooks' const { Value, onChange, call, cond, eq, abs, sub, min } = Animated const Modal = ({ children, snapPoints = [400, 0], initialSnap = null }) => { const sheet = useRef(null) const { closeModal } = useNavigation() const position = new Value(1) const opacity = min(abs(sub(position, 1)), 0.8) const zeroIndex = snapPoints.length - 1 const height = snapPoints[0] const handleOutsidePress = () => { sheet.current.snapTo(zeroIndex) } useEffect(() => { if (sheet.current) { sheet.current.snapTo(initialSnap || 0) } }, []) return ( <View style={{ flex: 1 }}> <TouchableWithoutFeedback onPress={handleOutsidePress}> <Animated.View style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, flex: 1, backgroundColor: '#000', opacity, }} /> </TouchableWithoutFeedback> <Animated.Code exec={onChange(position, [cond(eq(position, 1), call([], closeModal))])} /> <BottomSheet ref={sheet} initialSnap={zeroIndex} snapPoints={snapPoints} callbackNode={position} renderHeader={() => ( <View style={{ backgroundColor: 'rgba(255,255,255,0.5)', width: 50, height: 3, margin: 10, alignSelf: 'center', borderRadius: 3, }} /> )} renderContent={() => ( <View style={{ backgroundColor: '#fff', padding: 20, height, }} > {children} </View> )} /> </View> ) } Modal.propTypes = { children: PropTypes.any, snapPoints: PropTypes.array, initialSnap: PropTypes.number, } export default ModalUsage:
const SomeModal = () => { return ( <Modal snapPoints={[500, 0]}> <Text>My modal</Text> </Modal> ) }Works like a charm :)
state update then not working
it's solve thanks man
On Wed, Jan 22, 2020 at 5:50 PM Appasaheb notifications@github.com wrote:
I do like this:
import React, { useRef, useEffect } from 'react'
import PropTypes from 'prop-types'
import { View, TouchableWithoutFeedback } from 'react-native'
import BottomSheet from 'reanimated-bottom-sheet'
import Animated from 'react-native-reanimated'
import { useNavigation } from 'hooks'const { Value, onChange, call, cond, eq, abs, sub, min } = Animated
const Modal = ({ children, snapPoints = [400, 0], initialSnap = null }) => {
const sheet = useRef(null)
const { closeModal } = useNavigation()
const position = new Value(1)
const opacity = min(abs(sub(position, 1)), 0.8)
const zeroIndex = snapPoints.length - 1
const height = snapPoints[0]
const handleOutsidePress = () => {
sheet.current.snapTo(zeroIndex)
}useEffect(() => {
if (sheet.current) {
sheet.current.snapTo(initialSnap || 0)
}
}, [])return (
style={{
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
flex: 1,
backgroundColor: '#000',
opacity,
}}
/>
ref={sheet}
initialSnap={zeroIndex}
snapPoints={snapPoints}
callbackNode={position}
renderHeader={() => (
style={{
backgroundColor: 'rgba(255,255,255,0.5)',
width: 50,
height: 3,
margin: 10,
alignSelf: 'center',
borderRadius: 3,
}}
/>
)}
renderContent={() => (
style={{
backgroundColor: '#fff',
padding: 20,
height,
}}
>
{children}
)}
/>
)
}Modal.propTypes = {
children: PropTypes.any,
snapPoints: PropTypes.array,
initialSnap: PropTypes.number,
}export default Modal
Usage:
const SomeModal = () => {
return (
My modal
)
}Works like a charm :)
state update then not working
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/osdnk/react-native-reanimated-bottom-sheet/issues/46?email_source=notifications&email_token=AF4UYC5265G5YZ5JPCICS6DQ7A2YLA5CNFSM4HQRDNB2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEJTLDJY#issuecomment-577155495,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AF4UYC6H5NTFXI6IRBOMI43Q7A2YLANCNFSM4HQRDNBQ
.
Thank you for your work. Closing issue, because provided solution was approved.
Most helpful comment
I do like this:
Usage:
Works like a charm :)