Несколько экранов (например, стек) друг над другом в React Native

Можем ли мы в React Native создать пользовательский интерфейс, в котором есть несколько экранов, наложенных друг на друга, при этом каждый экран накладывается поверх другого при нажатии кнопки.

Допустим, есть экран A. При нажатии кнопки экран B размещается в виде стека на экране A, а экран A все еще частично виден, поскольку экран B не занимает всю компоновку экрана. Точно так же экран C добавляется в стек при нажатии кнопки на экране B, и экран B по-прежнему виден вместе с экраном A на заднем плане. Все это идет с боковой анимацией слева (аналогично навигационному ящику). С помощью общей кнопки все вышеперечисленные экраны могут быть вытолкнуты из стека, а предыдущий экран снова окажется наверху с боковой анимацией, на этот раз справа.

Я хотел понять, возможно ли это в React Native? Если да, то как я могу этого добиться? Я хотел бы показать дизайн, но я не могу сделать это в банкомате.


person Avinash Parasurampuram    schedule 25.03.2020    source источник


Ответы (2)


С помощью 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
    }
});

с вашими экранами на месте просмотров.

person William Brochensque junior    schedule 27.03.2020

Я мог бы добиться этой функциональности, используя очень классную библиотеку под названием «реагировать-нативный-модальфи».

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)

person Avinash Parasurampuram    schedule 01.04.2020