多个屏幕(像堆栈一样)彼此反应

时间:2020-03-25 03:37:50

标签: react-native react-native-android react-native-ios react-native-navigation stack-navigator

在react native中,我们能否实现一个UI,在该UI中,单击一个按钮,将多个屏幕彼此堆叠,而每个屏幕则堆叠在另一个屏幕之上。

比方说,有屏幕A。单击按钮后,屏幕B作为堆栈放置在屏幕A上,并且由于屏幕B并未占据整个屏幕布局,所以屏幕A仍部分可见。类似地,在单击屏幕B中的按钮时,屏幕C加到堆栈中,并且屏幕B与背景A在屏幕上仍然可见。所有这些都带有来自左侧的侧面动画(类似于导航抽屉)。使用一个通用按钮,可以从堆栈中弹出以上所有屏幕,并且上一个屏幕再次显示侧面动画,再次显示在顶部,这一次是在右侧。

我想了解一下是否可以在React Native中实现上述目标?如果可以,我该如何实现?我希望我可以展示设计,但是我不能这样做。

2 个答案:

答案 0 :(得分:1)

使用react-native-vertical-view-pager,您可以做到。

安装:

npm install --save react-native-vertical-view-pager

或与纱线(如果使用纱线):

yarn add react-native-vertical-view-pager

并按如下方式使用:

import React from 'react';
import { StyleSheet, Text, View, Dimensions } from 'react-native';
import VerticalViewPager from 'react-native-vertical-view-pager';

const { width, height } = Dimensions.get('window');

export default class App extends React.Component {
    render() {
        return (
            <VerticalViewPager
                showsVerticalScrollIndicator={false}>
                <View style={[styles.page_container, {backgroundColor: 'pink'}]}>
                    <Text>Page1: Open up App.js to start working on your app!</Text>
                </View>
                <View style={[styles.page_container, {backgroundColor: 'olive'}]}>
                    <Text>Page2: Changes you make will automatically reload.</Text>
                </View>
                <View style={[styles.page_container, {backgroundColor: 'lightblue'}]}>
                    <Text>Page3: Shake your phone to open the developer menu.</Text>
                </View>
            </VerticalViewPager>
        );
    }
}

const styles = StyleSheet.create({
    page_container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        width,
        height
    }
});

将屏幕置于视图位置。

答案 1 :(得分:0)

我可以使用一个非常酷的库“ react-native-modalfy”来实现此功能。

import React, { PureComponent } from 'react'
import {
  Easing,
  Dimensions,
  StatusBar,
  StyleSheet,
  Text,
  View,
} from 'react-native'
import { ModalProvider, createModalStack } from 'react-native-modalfy'

import CardModal from './modals/CardModal'
import Button from './components/Button'

const { width } = Dimensions.get('screen')

const config = { ModalA: CardModal, ModalB: CardModal, ModalC: CardModal }

const defaultOptions = {
  transitionOptions: animatedValue => ({
    opacity: animatedValue.interpolate({
      inputRange: [0, 1, 2],
      outputRange: [0, 1, .9],
    }),
    transform: [
      {
        perspective: 2000
      },
      {
        translateX: animatedValue.interpolate({
          inputRange: [0, 1, 2],
          outputRange: [-width / 2, 0, 25],
        }),
      },
      {
        scale: animatedValue.interpolate({
          inputRange: [0, 1, 2],
          outputRange: [1.2, 1, .9],
        }),
      },
    ],
  }),
  animateInConfig: {
    easing: Easing.bezier(.42,-0.03,.27,.95),
    duration: 450,
  },
  animateOutConfig: {
    easing: Easing.bezier(.42,-0.03,.27,.95),
    duration: 450,
  },
}

const stack = createModalStack(config, defaultOptions)

class App extends PureComponent {
  render() {
    return (
      <ModalProvider stack={stack}>
        <View style={styles.container}>
          <StatusBar animated hidden translucent />
          <Text style={styles.title}>RNM</Text>
          <Button label="Open ModalA" modalToOpen="ModalA" color="tomato" />
          <Button label="Open ModalB" modalToOpen="ModalB" color="darkcyan" />
          <Button label="Open ModalC" modalToOpen="ModalC" color="deeppink" />
        </View>
      </ModalProvider>
    )
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: 'indigo',
    alignItems: 'center',
    justifyContent: 'center'
  },
  title: {
    color: 'white',
    fontSize: 54,
    fontWeight: 'bold',
    marginBottom: 50,
  },
})

export default App

import React, { PureComponent } from 'react'
import {
  Button as ButtonModule,
  Dimensions,
  StyleSheet,
  Text,
  View,
} from 'react-native'

import Button from '../components/Button'

const { width: ww, height: wh } = Dimensions.get('screen')

class CardModal extends PureComponent {
  componentDidMount() {
    const { modal } = this.props
    this.modalListenerID = modal.addListener('onAnimate', this._handleAnimation)
  }

  componentWillUnmount() {
    this.modalListenerID?.remove()
  }

  _handleAnimation = animatedValue => {
    const { currentModal } = this.props.modal
    console.info(`${currentModal}:`, animatedValue)
  }

  render() {
    const {
      currentModal,
      closeModal,
      closeModals,
      closeAllModals,
      params: { color },
    } = this.props.modal

    return (
      <View style={[styles.card]}>
        <Text style={styles.title(color)}>{currentModal}</Text>
        <Button label="Open ModalA" modalToOpen="ModalA" color="tomato" />
        <Button label="Open ModalB" modalToOpen="ModalB" color="darkcyan" />
        <Button label="Open ModalC" modalToOpen="ModalC" color="deeppink" />
        
        <ButtonModule title="Close" onPress={closeModal} color="dodgerblue" />
        <ButtonModule title={`Close all ${currentModal}`} onPress={() => closeModals(currentModal)} color="dodgerblue" />
        <ButtonModule title="Close all modals" onPress={closeAllModals} color="red" />
      </View>
    )
  }
}

const styles = StyleSheet.create({
  title: color => ({
    color,
    fontSize: 48,
    fontWeight: 'bold',
    marginBottom: 50,
  }),
  card: {
    marginRight : 90,
    width: ww,
    height: wh,
    backgroundColor: 'cyan',
    elevation: 0,
    alignItems: 'center',
    justifyContent: 'center',
    borderRadius: 0,
  },
})

export default CardModal

import React, { PureComponent } from 'react'
import { TouchableOpacity, StyleSheet, Text } from 'react-native'
import { withModal } from 'react-native-modalfy'

class Button extends PureComponent {
  openModal = () => {
    const { color, modalToOpen, modal } = this.props

    modal.openModal(modalToOpen, { color })
  }

  render() {
    const { color, label } = this.props

    return (
      <TouchableOpacity onPress={this.openModal} style={styles.button(color)}>
        <Text style={styles.label}>{label}</Text>
      </TouchableOpacity>
    )
  }
}

const styles = StyleSheet.create({
  button: backgroundColor => ({
    backgroundColor,
    paddingHorizontal: 60,
    paddingVertical: 21,
    borderRadius: 21,
    marginBottom: 30,
  }),
  label: {
    fontSize: 16,
    fontWeight: '800',
    color: 'white',
    textAlign: 'center',
  },
})

export default withModal(Button)