Coder Social home page Coder Social logo

Comments (14)

lindesvard avatar lindesvard commented on September 2, 2024 3

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 :)

from react-native-reanimated-bottom-sheet.

levani avatar levani commented on September 2, 2024 1

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.

from react-native-reanimated-bottom-sheet.

ardyfeb avatar ardyfeb commented on September 2, 2024 1

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

from react-native-reanimated-bottom-sheet.

satya164 avatar satya164 commented on September 2, 2024

Put a TouchableWithoutFeedback underneath where you can add a onPress listener to dismiss.

from react-native-reanimated-bottom-sheet.

timothystewart6 avatar timothystewart6 commented on September 2, 2024

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>

from react-native-reanimated-bottom-sheet.

satya164 avatar satya164 commented on September 2, 2024

It needs to be positioned absolutely above your content, not wrap the content if I understand your code

from react-native-reanimated-bottom-sheet.

timothystewart6 avatar timothystewart6 commented on September 2, 2024

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.

from react-native-reanimated-bottom-sheet.

satya164 avatar satya164 commented on September 2, 2024

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.

TouchableWithoutFeedback requires at least one child component.

You can use an empty view

from react-native-reanimated-bottom-sheet.

nastarfan avatar nastarfan commented on September 2, 2024

@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

from react-native-reanimated-bottom-sheet.

AsadSaleh avatar AsadSaleh commented on September 2, 2024

@lindesvard
Are you using this https://reactnavigation.org/docs/en/next/use-navigation.html ?

from react-native-reanimated-bottom-sheet.

appasaheb4 avatar appasaheb4 commented on September 2, 2024

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 :)

state update then not working

from react-native-reanimated-bottom-sheet.

appasaheb4 avatar appasaheb4 commented on September 2, 2024

from react-native-reanimated-bottom-sheet.

BrtqKr avatar BrtqKr commented on September 2, 2024

Thank you for your work. Closing issue, because provided solution was approved.

from react-native-reanimated-bottom-sheet.

przbadu avatar przbadu commented on September 2, 2024

This is how I am handling it:

Basically, idea here is:

  • Always render bottom sheet content as 100% height
  • Then put upper portion with certain height and transparent background, e.g: 60%, which can be Tappable area, tapping on it, close the bottom sheet
  • Second 40% screen is for your bottom sheet content (agin, you can adjust these heights)
  function renderBottomSheetContent() {
    return (
      <View
        style={{
          height: '100%',
          display: 'flex',
          justifyContent: 'space-between',
        }}>

        <TouchableOpacity onPress={closeBottomSheet} style={{height: '60%'}} />

        <View
          style={{
            height: '40%',
            backgroundColor: COLORS.white,
            padding: SIZES.padding,
          }}>
          <Text>You can put both header and content in content section</Text>
        </View>

      </View>
    );
  }

from react-native-reanimated-bottom-sheet.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.