模态框是移动应用开发的重要组成部分,允许开发者以不引人注目的方式呈现信息或操作。在React Native中,模态框通常用于显示额外的内容,而无需导航到新的屏幕。
虽然React Native提供了一个基本的 Modal
组件,但是用它来创建自定义的、可滚动的模态框并提供无缝用户体验可能有些挑战性。幸运的是,react-native-modalize 库(又名Modalize)提供了一个优雅且灵活的解决方案,用于在React Native中构建高度可定制的滚动模态框。
在这篇文章中,我们将探索如何在 React Native 中使用Modalize轻松创建自定义滚动内容模态。你可以在GitHub上找到本教程中使用的完整代码。
设置 react-native-modalize
Modalize 是一个受欢迎的开源库。它提供了一个高级的模态组件,提供平滑自然的滚动行为,使其成为显示各种内容的理想选择,从简单的文本到复杂的表单或列表。该库是在 React Native的 Animated API 之上构建的,确保平滑的动画和过渡,会给您的用户留下深刻的印象。
首先,我们将在终端运行下面的命令来创建一个新的 React Native 项目:
npx react-native init <project-name-here>
接下来,使用npm或Yarn安装 Modalize:
npm install react-native-modalize
# or
yarn add react-native-modalize
这个库依赖于React Native Gesture Handler,所以我们将在我们的项目中安装它:
yarn add react-native-gesture-handler
# or
npm install react-native-gesture-handler
对于手势处理器版本≥2.0.0,我们需要按照以下步骤使其工作:
- 用
GestureHandlerRootView
组件包裹你的应用程序入口点 - 在
index.js
文件顶部导入react-native-gesture-handler
经过以上的修改,你的 index.js
和 App.tsx
文件将会如下所示:
// index.js
// Add this 👇
import 'react-native-gesture-handler';
import {AppRegistry} from 'react-native';
import App from './App';
import {name as appName} from './app.json';
AppRegistry.registerComponent(appName, () => App);
// App.tsx
import {SafeAreaView, StyleSheet, Text} from 'react-native';
import {GestureHandlerRootView} from 'react-native-gesture-handler';
const App = () => {
return (
<GestureHandlerRootView style={styles.container}>
<SafeAreaView style={styles.container}>
<Text>{'Open Modal'}</Text>
</SafeAreaView>
</GestureHandlerRootView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
});
export default App;
安装了手势处理器后,我们现在可以深入创建自定义滚动模态,这将提升我们的React Native应用中的用户体验。
使用react-native-modalize来定制模态框
我们从实现一个基础示例开始,以理解如何有效地使用 Modalize。为此,我们将创建一个显示一些文本的简单模态框。
在你的 App.tsx
文件中添加以下代码:
import {useRef} from 'react';
import {SafeAreaView, StyleSheet, Text, View} from 'react-native';
import {GestureHandlerRootView} from 'react-native-gesture-handler';
import {Modalize} from 'react-native-modalize';
const App = () => {
const modalRef = useRef<Modalize>(null);
const openModal = () => modalRef?.current?.open();
return (
<GestureHandlerRootView style={styles.container}>
<SafeAreaView style={styles.container}>
<Text onPress={openModal}>{'Open Modal'}</Text>
<Modalize ref={modalRef}>
<View style={{padding: 20}}>
<Text style={{fontSize: 22, fontWeight: 'bold', lineHeight: 34}}>
{'This is a modal'}
</Text>
<Text>
{
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed et euismod nisl. Nulla facilisi. Aenean et mi volutpat, iaculis libero non, luctus quam. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Curabitur euismod dapibus metus, eget egestas quam ullamcorper eu.'
}
</Text>
</View>
</Modalize>
</SafeAreaView>
</GestureHandlerRootView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#ddd',
},
});
export default App;
在这里,我们为我们的模态框创建了一个名为 modalRef
的 ref
,并将其分配给我们的 Modalize
组件。 Modalize 组件包裹了我们想在模态框内显示的内容。 ref
属性允许我们访问模态框的方法,例如打开和关闭它。
上述代码给我们以下输出:
处理可滚动内容
使用 Modalize 的一个重要优势是其高度的定制性。你可以定制模态以匹配你的应用的设计和用户体验需求。
默认情况下,使用 react-native-modalize
构建的任何模态框中的内容,如果超过模态框的高度,将自动可滚动。这使您可以展示长篇信息,而无需担心内容溢出。
让我们看看如果我们的内容大于模态框的高度会发生什么。修改 Modalize 组件中的代码,如下所示:
<Modalize
ref={modalRef}
modalHeight={200}
scrollViewProps={{showsVerticalScrollIndicator: false}}>
<View style={{padding: 20}}>
<Text style={{fontSize: 22, fontWeight: 'bold', lineHeight: 34}}>
{'This is a modal'}
</Text>
<Text>
{
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed et euismod nisl. Nulla facilisi. Aenean et mi volutpat, iaculis libero non, luctus quam. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Curabitur euismod dapibus metus, eget egestas quam ullamcorper eu.'
}
{'\n\n'}
{
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed et euismod nisl. Nulla facilisi. Aenean et mi volutpat, iaculis libero non, luctus quam. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Curabitur euismod dapibus metus, eget egestas quam ullamcorper eu.'
}
</Text>
</View>
</Modalize>
我们已经明确地将我们的模态框的高度设置为 200
,并使用 scrollViewProps
来隐藏滚动指示器。 Modalize 将自动将内容包裹在 ScrollView
内。现在让我们看看我们的模态框现在是什么样子:
使用 Snap points
"Snap points" 指的是模态框在打开或关闭时可以动画化到的特定位置。模态框在打开或关闭的动画过程中,可以在预定义的高度停止,而不是立即平滑过渡到其完全高度。这种行为允许你以不同的状态或大小展示模态框,增强用户体验并提供更动态的交互。
许多第三方模态库——包括Modalize——都提供了一个 snapPoint
属性,允许你定义这些吸附点。当模态框打开时,它会平滑地动画到指定的吸附点;当关闭时,它会动画回到其起始位置或另一个指定的吸附点。
使用下面的代码更新你的 Modalize
声明,看看我们如何使用捕捉点:
<Modalize
ref={modalRef}
modalHeight={600}
snapPoint={300}
closeSnapPointStraightEnabled={false}
scrollViewProps={{showsVerticalScrollIndicator: false}}>
<View style={{padding: 20}}>
<Text style={{fontSize: 22, fontWeight: 'bold', lineHeight: 34}}>
{'This is a modal'}
</Text>
<Text>
{
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed et euismod nisl. Nulla facilisi. Aenean et mi volutpat, iaculis libero non, luctus quam. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Curabitur euismod dapibus metus, eget egestas quam ullamcorper eu.'
}
{'\n\n'}
{
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed et euismod nisl. Nulla facilisi. Aenean et mi volutpat, iaculis libero non, luctus quam. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Curabitur euismod dapibus metus, eget egestas quam ullamcorper eu.'
}
</Text>
</View>
</Modalize>
在这个例子中, snapPoint
属性被设置为 300
。这意味着当模态框打开时,它将平滑地动画到300个单位的高度。当模态框关闭时,它将动画回到其起始位置。
closeSnapPointStraightEnabled
表示在关闭时,模态是否应在捕捉点停止。当设置为 false
时,模态在关闭前会在捕捉点停止,反之则在设置为 true
时。默认情况下,其值为 true
。
渲染一个 FlatList
Modalize 默认使用 ScrollView
作为其渲染器,但它也允许我们使用 FlatList
或 SectionList
作为渲染器。让我们看看如何使用 FlatList
作为我们的 Modalize 组件的渲染器。
我们将以下代码添加到我们的 App.tsx 中:
// <imports here>
const DATA = [
{
id: '1',
title: 'First Item',
imgUrl: 'https://picsum.photos/800',
},
// Other 9 Items like this here
];
const App = () => {
const flatlistModalRef = useRef<Modalize>(null);
const openFlatListModal = () => flatlistModalRef?.current?.open();
const renderItem = ({item}) => (
<View
style={{
flexDirection: 'row',
alignItems: 'center',
paddingVertical: 16,
}}>
<Image
source={{uri: item?.imgUrl}}
style={{
height: 100,
width: 100,
borderRadius: 20,
marginHorizontal: 16,
}}
/>
<Text style={{fontWeight: '700', fontSize: 24, letterSpacing: 1.4}}>
{item?.title}
</Text>
</View>
);
return (
<GestureHandlerRootView style={styles.container}>
<SafeAreaView style={styles.container}>
<Text onPress={openFlatListModal}>{'Open FlatList Modal'}</Text>
<Modalize
ref={flatlistModalRef}
modalTopOffset={80}
flatListProps={{
data: DATA,
keyExtractor: item => item.id,
showsVerticalScrollIndicator: false,
renderItem,
}}
/>
</SafeAreaView>
</GestureHandlerRootView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#ddd',
},
});
export default App;
在上面,我们使用了Modalize的 flatListProps
来初始化我们的 FlatList 在模态框内。这些是我们在创建 List 时传入 FlatList
的标准属性。
上述代码创建了以下的模态列表:
创建一个始终开启的模态框
我们可以在 react-native-modalize
中使用 alwaysOpen
属性来控制模态框的行为,确保它始终在屏幕上打开并可见。当设置为任何数值时,模态框将无法关闭,并且它将以给定的高度显示,用户无法关闭它。
我们在我们的 FlatList 模态框中添加以下属性:
<Modalize
ref={flatlistModalRef}
modalTopOffset={80}
// Add this 👇
alwaysOpen={140}
flatListProps={{
data: DATA,
keyExtractor: item => item.id,
showsVerticalScrollIndicator: false,
renderItem,
}}
/>
这将使我们的模态框始终以140单位的高度打开:
在你想要展示必须始终可见的重要信息或指示的场景中,你可能会使用 alwaysOpen
属性。例如,你可以使用它来显示重要的公告,或者用户在与应用的其余部分进行交互之前需要阅读的教程。
因为 alwaysOpen
在任何情况下都阻止用户关闭模态,所以必须谨慎使用它。否则,可能会严重影响你的应用的用户体验。
如果模态框内的信息对用户的交互至关重要,那么它可能是一个合适的选择。但是对于用户可能合理地想要关闭的内容,考虑使用模态框的默认行为或提供一个关闭按钮。
总结
在React Native中,使用 react-native-modalize
库创建自定义的滚动模态框非常简单。其灵活性和众多的自定义选项使它成为希望提供卓越用户体验的开发者的优秀选择。
我们探索了使用Modalize的基础知识,并学习了如何实现一个带有滚动内容的自定义模态框。我们还涉及到了库中一些基本的自定义选项,如使用捕捉点,在模态框中渲染 FlatList ,以及配置始终打开的模态框。再次强调,你可以在这里的GitHub仓库中找到我们在本教程中使用的全部代码。
首发于公众号 大迁世界,欢迎关注。📝 每周一篇实用的前端文章 🛠️ 分享值得关注的开发工具 ❓ 有疑问?我来回答
本文 GitHub https://github.com/qq449245884/xiaozhi 已收录,有一线大厂面试完整考点、资料以及我的系列文章。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。