如何在React Native中从底部滑入<View />?

Jo *_* Ko 16 javascript reactjs react-jsx react-native redux

在React Native iOS中,我想在图片中滑入和滑出.

在下面的示例中,当按下按钮时,Payment Information视图从底部弹出,按下折叠按钮时,它会向下并消失.

这样做的正确和正确的方法是什么?

在此输入图像描述

先感谢您!

编辑

在此输入图像描述

Ahm*_*dad 24

基本上,您需要将视图绝对定位到屏幕底部.然后将其y值转换为等于其高度.(子视图必须具有特定高度才能知道移动多少)

这是一个展示结果的游乐场:https: //rnplay.org/apps/n9Gxfg

码:

'use strict';

import React, {Component} from 'react';
import ReactNative from 'react-native';

const {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  TouchableHighlight,
  Animated
} = ReactNative;


var isHidden = true;

class AppContainer extends Component {
  constructor(props) {
    super(props);
    this.state = {
      bounceValue: new Animated.Value(100),  //This is the initial position of the subview
      buttonText: "Show Subview"
    };
  }


  _toggleSubview() {    
    this.setState({
      buttonText: !isHidden ? "Show Subview" : "Hide Subview"
    });

    var toValue = 100;

    if(isHidden) {
      toValue = 0;
    }

    //This will animate the transalteY of the subview between 0 & 100 depending on its current state
    //100 comes from the style below, which is the height of the subview.
    Animated.spring(
      this.state.bounceValue,
      {
        toValue: toValue,
        velocity: 3,
        tension: 2,
        friction: 8,
      }
    ).start();

    isHidden = !isHidden;
  }

  render() {
    return (
      <View style={styles.container}>
          <TouchableHighlight style={styles.button} onPress={()=> {this._toggleSubview()}}>
            <Text style={styles.buttonText}>{this.state.buttonText}</Text>
          </TouchableHighlight>
          <Animated.View
            style={[styles.subView,
              {transform: [{translateY: this.state.bounceValue}]}]}
          >
            <Text>This is a sub view</Text>
          </Animated.View>
      </View>
    );
  }
}

var styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
    marginTop: 66
  },
  button: {
    padding: 8,
  },
  buttonText: {
    fontSize: 17,
    color: "#007AFF"
  },
  subView: {
    position: "absolute",
    bottom: 0,
    left: 0,
    right: 0,
    backgroundColor: "#FFFFFF",
    height: 100,
  }
});

AppRegistry.registerComponent('AppContainer', () => AppContainer);
Run Code Online (Sandbox Code Playgroud)


Alb*_*lvo 14

我创建了一个接受任何内容的可重用 BottomSheet组件。

它是这样的:

在此输入图像描述

这是该组件的代码(TypeScript)BottomSheet

import * as React from 'react'
import {
  Animated,
  Easing,
  Pressable,
  StyleSheet,
  useWindowDimensions,
  View,
} from 'react-native'

const DEFAULT_HEIGHT = 300

function useAnimatedBottom(show: boolean, height: number = DEFAULT_HEIGHT) {
  const animatedValue = React.useRef(new Animated.Value(0))

  const bottom = animatedValue.current.interpolate({
    inputRange: [0, 1],
    outputRange: [-height, 0],
  })

  React.useEffect(() => {
    if (show) {
      Animated.timing(animatedValue.current, {
        toValue: 1,
        duration: 350,
        // Accelerate then decelerate - https://cubic-bezier.com/#.28,0,.63,1
        easing: Easing.bezier(0.28, 0, 0.63, 1),
        useNativeDriver: false, // 'bottom' is not supported by native animated module
      }).start()
    } else {
      Animated.timing(animatedValue.current, {
        toValue: 0,
        duration: 250,
        // Accelerate - https://easings.net/#easeInCubic
        easing: Easing.cubic,
        useNativeDriver: false,
      }).start()
    }
  }, [show])

  return bottom
}

interface Props {
  children: React.ReactNode
  show: boolean
  height?: number
  onOuterClick?: () => void
}

export function BottomSheet({
  children,
  show,
  height = DEFAULT_HEIGHT,
  onOuterClick,
}: Props) {
  const { height: screenHeight } = useWindowDimensions()

  const bottom = useAnimatedBottom(show, height)

  return (
    <>
      {/* Outer semitransparent overlay - remove it if you don't want it */}
      {show && (
        <Pressable
          onPress={onOuterClick}
          style={[styles.outerOverlay, { height: screenHeight }]}
        >
          <View />
        </Pressable>
      )}
      <Animated.View style={[styles.bottomSheet, { height, bottom }]}>
        {children}
      </Animated.View>
    </>
  )
}

const styles = StyleSheet.create({
  outerOverlay: {
    position: 'absolute',
    width: '100%',
    zIndex: 1,
    backgroundColor: 'black',
    opacity: 0.3,
  },
  bottomSheet: {
    position: 'absolute',
    width: '100%',
    zIndex: 1,
    // Here you can set a common style for all bottom sheets, or nothing if you
    // want different designs
    backgroundColor: 'dodgerblue',
    borderRadius: 16,
  },
})
Run Code Online (Sandbox Code Playgroud)

我把这段代码放在一个名为BottomSheet.tsx.

这是您使用的方式BottomSheet

import * as React from 'react'
import {
  Pressable,
  SafeAreaView,
  StatusBar,
  StyleSheet,
  Text,
  View,
} from 'react-native'
import { BottomSheet } from './src/BottomSheet'

const App = () => {
  const [showBottomSheet, setShowBottomSheet] = React.useState(false)

  const hide = () => {
    setShowBottomSheet(false)
  }

  return (
    <SafeAreaView style={styles.safeAreaView}>
      <StatusBar barStyle={'dark-content'} />
      <View style={styles.container}>
        <Pressable
          onPress={() => {
            setShowBottomSheet(true)
          }}
          style={styles.showButton}
        >
          <Text style={styles.buttonText}>Show bottom sheet</Text>
        </Pressable>
      </View>

      <BottomSheet show={showBottomSheet} height={290} onOuterClick={hide}>
        <View style={styles.bottomSheetContent}>
          <Text style={styles.bottomSheetText}>Hey boys, hey girls!</Text>
          <Pressable onPress={hide} style={styles.bottomSheetCloseButton}>
            <Text style={styles.buttonText}>X Close</Text>
          </Pressable>
        </View>
      </BottomSheet>
    </SafeAreaView>
  )
}

const styles = StyleSheet.create({
  safeAreaView: {
    flex: 1,
  },
  container: {
    flex: 1,
  },
  showButton: {
    marginTop: 48,
    padding: 16,
    backgroundColor: 'mediumspringgreen',
    alignSelf: 'center',
    borderRadius: 8,
  },
  buttonText: {
    fontSize: 20,
  },
  bottomSheetContent: {
    padding: 40,
    alignItems: 'center',
  },
  bottomSheetText: {
    fontSize: 24,
    marginBottom: 80,
  },
  bottomSheetCloseButton: {
    padding: 16,
    backgroundColor: 'deeppink',
    borderRadius: 8,
  },
})

export default App
Run Code Online (Sandbox Code Playgroud)

笔记:

  • 我已经放置了外部半透明覆盖层,但您可以通过删除它来摆脱它。
  • 我选择在您单击外部半透明覆盖层时关闭模式。这是通过onOuterClick回调完成的,回调是可选的 - 如果您不想执行任何操作,则不要传递它。
  • 我已经设置了一些适用于所有底部工作表的样式(蓝色背景+边框半径),但如果您想要不同的样式,可以将其删除。


edv*_*lme 8

我知道这有点晚了,但认为对某人可能有用。您应该尝试一个名为的组件rn-sliding-out-panel。它很棒。https://github.com/octopitus/rn-sliding-up-panel

<SlidingUpPanel
    draggableRange={top: 1000, bottom: 0}
    showBackdrop={true|false /*For making it modal-like*/}
    ref={c => this._panel = c}
    visible={ture|false /*If you want it to be visible on load*/}
></SlidingUpPanel>
Run Code Online (Sandbox Code Playgroud)

您甚至可以从外部按钮打开它:

<Button onPress={()=>{this._panel.transitionTo(1000)}} title='Expand'></Button>
Run Code Online (Sandbox Code Playgroud)

您可以通过npm:将其安装sudo npm install rn-sliding-out-panel --save在react-native根目录上。


我希望它可以帮助某人:D