question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[Suggestion Needed] Dismissing bottom sheet when tapping outside of bottom sheet

See original GitHub issue

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!

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:14 (5 by maintainers)

github_iconTop GitHub Comments

3reactions
lindesvardcommented, Jun 4, 2019

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 😃

1reaction
ardyfebcommented, Jul 26, 2019

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 😃

using this code, scrollview outside <View style={{ flex: 1 }}> cannot be scrolled

Read more comments on GitHub >

github_iconTop Results From Across the Web

Prevent dismissal of BottomSheetDialogFragment on touch ...
According to the BottomSheet specification bottom sheets can be dismissed by touching outside of the bottom sheet, therefore what are my options ...
Read more >
Sheets: bottom - Material Design
If the content outside of the dialog is tapped then the bottom sheet is dismissed. Modal bottom sheets can be dragged vertically and...
Read more >
Sheets - Presentation - Human Interface Guidelines - Design
Support swiping to dismiss a sheet. People expect to swipe vertically to dismiss a sheet instead of tapping a dismiss button. If people...
Read more >
Jetpack Compose bottom sheet over Android view using ...
This article will teach us how to build Kotlin extensions for Activity and fragment to display bottom sheets using Jetpack compose.
Read more >
Introducing Navigation-Material 🎨️ | by Jossi Wolf - Medium
You can navigate away from bottom sheet destinations as usual, or the user can dismiss the sheet by tapping on the scrim or...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found