在React Native中创建一个弹出式模态

模态是改善用户界面的一个伟大工具。从本质上讲,模态是一个出现在另一个屏幕之上的屏幕,将用户的注意力引向关键信息或引导他们进入流程中的下一个步骤。一个激活的模态会使原来的屏幕失效,而原来的屏幕仍然是可见的,提示用户与新的屏幕进行交互。

在本教程中,我们将看看模态的一些实际用例,并通过在React Native中创建以下内容来提高我们对模态的理解。

  • 一个在用户点击按钮时打开的模态
  • 一个带有子组件的可重用模态
  • 当用户导航到一个屏幕时打开的弹出式模态

你可以在我的GitHub上找到这个项目的源代码。

初始化该项目

首先,为了初始化这个项目,在你的终端中输入以下代码。

expo init projectName && cd projectName && expo start

复制代码

如果你要把模版添加到一个现有的项目中,而不是从头开始,跳过这一步,把react-native-modal 添加到你的项目中,并选择标题选项。

选择tabs (TypeScript) 选项,它应该看起来像下面的代码块。

tabs (TypeScript)     several example screens and tabs using react-navigation and TypeScript

复制代码

一个浏览器窗口将弹出,上面有打开Expo项目的说明。现在,你可以打开你喜欢的IDE。如果你使用的是VS代码,在终端输入code . 来打开它。

安装react-native-modal

react-native-modal ,如果你把React Native的模态组件带到美容院,并要求进行全面改造,你会得到什么。它建立在React Native的模态组件上,提供了漂亮的动画和可定制的样式选项。

运行下面的代码来安装react-native-modal

yarn add react-native-modal

复制代码

创建一个基本的模态

模态是由前面的动作触发的,比如导航到/从一个屏幕或点击一个按钮。

打开screens/TabOneScreen 。把代码改成下面的代码块的样子。

import * as React from "react";
import { Button, StyleSheet, Text, View } from "react-native";
import Modal from "react-native-modal";

export default function TabOneScreen() {

  const [isModalVisible, setIsModalVisible] = React.useState(false);

  const handleModal = () => setIsModalVisible(() => !isModalVisible);

  return (
    <View style={styles.container}>
      <Text style={styles.title}>Tab One</Text>
      <View style={styles.separator} />
      <Button title="button" onPress={handleModal} />
      <Modal isVisible={isModalVisible}>
        <View style={{ flex: 1 }}>
          <Text>Hello!</Text>
          <Button title="Hide modal" onPress={handleModal} />
        </View>
      </Modal>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: "center",
    justifyContent: "center",
  },
  title: {
    fontSize: 20,
    fontWeight: "bold",
  },
  text: {
    fontSize: 16,
    fontWeight: "400",
    textAlign: "center",
  },
  separator: {
    marginVertical: 30,
    height: 1,
    width: "80%",
  },
});

复制代码

让我们仔细看一下。

useState

const [isModalVisible, setIsModalVisible] = React.useState(false);

复制代码

ReactuseState Hook返回isModalVisible ,一个有状态的值,以及setIsModalVisible ,一个更新它的函数。

初始状态是false ,所以在我们改变状态之前,我们不能看到模态。在我们的例子中,我们将使用一个按钮。

handleModal

const handleModal = () => setIsModalVisible(() => !isModalVisible);

复制代码

按下按钮将调用handleModal ,并返回相反的状态。真变成假,假变成真。

<Modal />

<Modal isVisible={isModalVisible}>

复制代码

Modal 有一个叫做isVisible 的属性,它接受一个布尔值。因为我们把isModalVisible 传递给isVisible ,模态知道它应该什么时候出现。

你完成的模态将看起来像下面的图片。

Finished Basic React Native Modal

创建一个可重用的模态

前面的例子创建了一个模态和用于打开和关闭它的按钮。现在我们知道了这些步骤,让我们建立一个自定义的模态和一个用于启动它的按钮。

让我们从一个简单的按钮开始,以打开和关闭我们的模态。在components 文件夹中,创建一个名为Button.tsx 的新文件并添加以下代码。

import React from "react";
import { StyleSheet, Text, TouchableOpacity, View } from "react-native";
export type ButtonProps = {
  title: string;
  onPress: () => void;
};
export const Button = ({ title, onPress }: ButtonProps) => {
  return (
    <TouchableOpacity style={styles.button} onPress={onPress}>
      <Text style={styles.text}>{title}</Text>
    </TouchableOpacity>
  );
};
const styles = StyleSheet.create({
  button: {
    backgroundColor: "blue",
    marginTop: 15,
    paddingVertical: 15,
    borderRadius: 25,
    width: "80%",
    alignItems: "center",
  },
  text: {
    color: "white",
    fontWeight: "700",
    fontSize: 18,
  },
});

复制代码

你的输出应该看起来像下面的图片。

Button React Native Modal

现在我们已经建立了一个按钮,我们将创建我们的模态。在你的components 文件夹中,创建一个名为Modal.tsx 的文件并添加以下代码。

import React from "react";
import { StyleSheet, View, Text, Button } from "react-native";
import RNModal from "react-native-modal";
type ModalProps = {
  isVisible: boolean;
  children: React.ReactNode;
  [x: string]: any;
};
export const Modal = ({
  isVisible = false,
  children,
  ...props
}: ModalProps) => {
  return (
    <RNModal
      isVisible={isVisible}
      animationInTiming={1000}
      animationOutTiming={1000}
      backdropTransitionInTiming={800}
      backdropTransitionOutTiming={800}
      {...props}>
      {children}
    </RNModal>
  );
};

const ModalContainer = ({ children }: { children: React.ReactNode }) => (
  <View style={styles.container}>{children}</View>
);

const ModalHeader = ({ title }: { title: string }) => (
  <View style={styles.header}>
    <Text style={styles.text}>{title}</Text>
  </View>
);

const ModalBody = ({ children }: { children?: React.ReactNode }) => (
  <View style={styles.body}>{children}</View>
);

const ModalFooter = ({ children }: { children?: React.ReactNode }) => (
  <View style={styles.footer}>{children}</View>
);

const styles = StyleSheet.create({
  container: {
    backgroundColor: "#ffffff",
    borderRadius: 25,
    borderWidth: 1,
    borderColor: "#000",
    borderStyle: "solid",
  },
  header: {
    alignItems: "center",
    justifyContent: "center",
  },
  text: {
    paddingTop: 10,
    textAlign: "center",
    fontSize: 24,
  },
  body: {
    justifyContent: "center",
    paddingHorizontal: 15,
    minHeight: 100,
  },
  footer: {
    justifyContent: "center",
    alignItems: "center",
    padding: 10,
    flexDirection: "row",
  },
});

Modal.Header = ModalHeader;
Modal.Container = ModalContainer;
Modal.Body = ModalBody;
Modal.Footer = ModalFooter;

复制代码

我们已经将第一个例子中的原始模态组件导出为Modal 。你注意到animationbackdropTransitions 道具了吗?这些道具就是我所说的给原生模态组件进行改造的东西。

关于可用道具的完整列表,请查看文档

子组件和点符号

使用符号,我们将导出Modal ,作为一个带有子组件的模块。如果你想添加一个页眉,你可以用Modal.Header 访问页眉组件。

ModalHeader 接受title 道具中的一个字符串。Modal.Container,Modal.Body, 和Modal.Footer 接受子组件。子组件可以是任何你想要的东西,比如一张图片、一些文本、按钮或一个ScrollView

现在我们有了一个模态和一个按钮,回到screens/TabOneScreen 。只需两个步骤,我们就可以把它放在一起。

通过将上面的代码块中的导入语句改为下面的代码块,导入我们的新按钮和模态。

import { Button, StyleSheet, Text, View } from "react-native";
import Modal from "react-native-modal";


import { StyleSheet, Text, View } from "react-native";
import { Button } from "../components/Button";
import { Modal } from "../components/Modal";

复制代码

对返回语句中的模态组件做同样的处理。

<Modal isVisible={isModalVisible}>
  <View style={{ flex: 1 }}>
    <Text>Hello!</Text>
    <Button title="Hide modal" onPress={handleModal} />
  </View>
</Modal>


<Modal isVisible={isModalVisible}>
  <Modal.Container>
    <Modal.Header title="LogRocket is fab!" />
    <Modal.Body>
      <Text style={styles.text}>Agree to continue with this guide</Text>
      </Modal.Body>
    <Modal.Footer>
      <Button title="I agree" onPress={handleModal} />
    </Modal.Footer>
  </Modal.Container>
</Modal>

复制代码

结果应该类似于下面的图片。

Reusable React Native Modal Buttons Dot Notation

你可以在GitHub上找到所有的修改

创建一个弹出式模态

现在,我们有一个模态,当我们告诉它时,它就会出现。让我们添加一些弹出式窗口,在我们想提示用户看或做什么的时候出现。为了开始,我们将创建一个行动呼吁的场景。

例子

让我们假设一个用户必须订阅才能访问一个特定的屏幕。我们想在用户进入该屏幕但没有订阅的情况下创建一个行动呼吁。

screens/TabTwoScreen ,把当前的代码换成下面的代码。

import React, { useEffect } from "react";
import { StyleSheet, Text, TextInput, View } from "react-native";
import { Button } from "../components/Button";
import { Modal } from "../components/Modal";

export default function TabTwoScreen() {
  const [isModalVisible, setIsModalVisible] = React.useState(false);

  useEffect(() => {
    const checkForSubscription = setTimeout(() => {
      setIsModalVisible(() => !isModalVisible);
    }, 1500);
    return () => clearTimeout(checkForSubscription);
  }, []);

  const handleSignUp = () => {
    // sign up the user and close the modal
    setIsModalVisible(() => !isModalVisible);
  };

  const handleDecline = () => setIsModalVisible(() => !isModalVisible);

  return (
    <View style={styles.container}>
      <Text style={styles.title}>Premium stuff here</Text>
      <View style={styles.separator} />
      <Modal isVisible={isModalVisible}>
        <Modal.Container>
          <View style={styles.modal}>
            <Modal.Header title="You're just one step away!" />
            <Modal.Body>
              <Text style={styles.text}>
                Want access? We just need your email address
              </Text>
              <TextInput
                style={styles.input}
                placeholder="email"
                keyboardType="email-address"
              />
            </Modal.Body>
            <Modal.Footer>
              <View style={styles.button}>
                <Button title="No thanks" onPress={handleDecline} />
                <Button title="Sign me up!" onPress={handleSignUp} />
              </View>
            </Modal.Footer>
          </View>
        </Modal.Container>
      </Modal>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: "center",
    justifyContent: "center",
  },
  title: {
    fontSize: 20,
    fontWeight: "bold",
  },
  text: {
    fontSize: 16,
    fontWeight: "400",
    textAlign: "center",
  },
  separator: {
    marginVertical: 30,
    height: 1,
    width: "80%",
  },
  input: {
    paddingTop: 10,
    borderColor: "grey",
    borderBottomWidth: 2,
  },
  button: {
    flexDirection: "row",
    flex: 1,
    justifyContent: "center",
  },
  modal: {
    width: "100%",
    height: "90%",
    alignItems: "center",
    justifyContent: "center",
  },
});

复制代码

当依赖数组中的依赖关系发生变化时,useEffect 会重新显示,由[] 表示。useEffect ,当你导航到屏幕时,会出现Modal 组件。

由于我们没有传递任何依赖关系,useEffect 将只渲染一次。setTimeout 用于模拟检查用户是否订阅。

useEffect(() => {
    // fake check to see if user is subscribed
    const checkForSubscription = setTimeout(() => {
      setIsModalVisible(() => !isModalVisible);
    }, 1500);
    return () => clearTimeout(checkForSubscription);
    // dependancy array 
  }, []);

复制代码

你的模态应该看起来像下面的图片。

Finished React Native Pop Up Module

总结

在本教程中,我们已经了解了什么是模态以及它们如何工作。然后我们创建了三个自定义模态,可以改善任何React Native应用程序。

正如你所看到的,模态是实现行动召唤的一个伟大工具。还有几个类似的库,比如react-native-modal-date-picker,所以值得在npm上浏览一下。根据你的使用情况,你可能会节省一些时间来构建一个定制的组件

我希望你喜欢在本教程中学习模态。编码愉快

The postCreating a pop-up modal in React Native appeared first onLogRocket Blog.

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享