模态是改善用户界面的一个伟大工具。从本质上讲,模态是一个出现在另一个屏幕之上的屏幕,将用户的注意力引向关键信息或引导他们进入流程中的下一个步骤。一个激活的模态会使原来的屏幕失效,而原来的屏幕仍然是可见的,提示用户与新的屏幕进行交互。
在本教程中,我们将看看模态的一些实际用例,并通过在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
,模态知道它应该什么时候出现。
你完成的模态将看起来像下面的图片。
创建一个可重用的模态
前面的例子创建了一个模态和用于打开和关闭它的按钮。现在我们知道了这些步骤,让我们建立一个自定义的模态和一个用于启动它的按钮。
让我们从一个简单的按钮开始,以打开和关闭我们的模态。在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,
},
});
复制代码
你的输出应该看起来像下面的图片。
现在我们已经建立了一个按钮,我们将创建我们的模态。在你的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
。你注意到animation
和backdropTransitions
道具了吗?这些道具就是我所说的给原生模态组件进行改造的东西。
关于可用道具的完整列表,请查看文档。
子组件和点符号
使用点符号,我们将导出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>
复制代码
结果应该类似于下面的图片。
创建一个弹出式模态
现在,我们有一个模态,当我们告诉它时,它就会出现。让我们添加一些弹出式窗口,在我们想提示用户看或做什么的时候出现。为了开始,我们将创建一个行动呼吁的场景。
例子
让我们假设一个用户必须订阅才能访问一个特定的屏幕。我们想在用户进入该屏幕但没有订阅的情况下创建一个行动呼吁。
到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
}, []);
复制代码
你的模态应该看起来像下面的图片。
总结
在本教程中,我们已经了解了什么是模态以及它们如何工作。然后我们创建了三个自定义模态,可以改善任何React Native应用程序。
正如你所看到的,模态是实现行动召唤的一个伟大工具。还有几个类似的库,比如react-native-modal-date-picker,所以值得在npm上浏览一下。根据你的使用情况,你可能会节省一些时间来构建一个定制的组件
我希望你喜欢在本教程中学习模态。编码愉快
The postCreating a pop-up modal in React Native appeared first onLogRocket Blog.