弹窗组件允许开发者创建一个可以覆盖屏幕内容的视图,通常用于显示表单、菜单或其他需要用户交互的组件。在原生开发中可以使用ActionSheet来实现底部弹框,在React Native开发中,官方虽然提供了Modal组件来实现弹框效果,但是Modal组件使用起来并不方便,所以推荐大家使用react-native-modal。
react-native-modal是一个增强的,动画的和可定制的react-native模态对话框开源组件,它提供的API比较丰富,基本可以满足开发中需要的各种对话弹框,它附带遮罩层以模态的形式弹出。具有如下一些特点:
- 增强型和可定制:react-native-modal 提供了比React Native 核心组件 Modal 更丰富的功能和定制选项。
- 动画支持:它内置了流畅的进入和退出动画效果,使模态框的显示和隐藏更加自然。
- 灵活的API:开发者可以轻松地配置模态框的各种属性,如背景的不透明度、颜色、动画类型等。
- 易于集成:该组件易于集成到React Native 项目中,并且提供了简单的API,方便开发者使用。
- 模态形式的弹出:react-native-modal 以模态形式弹出,可以用于展示重要信息、提示用户操作或收集用户输入。
在RN项目中使用react-native-modal需要先安装插件:
npm install react-native-modal --save
然后就可以使用react-native-modal提供的Modal组件来实现各种弹框效果了,以下是使用Modal组件实现底部弹框的示例代码:
import { StyleSheet, Text, TouchableOpacity, TouchableWithoutFeedback, View } from "react-native";
import Modal from 'react-native-modal';
export type Option = {
label: string;
value: string;
};
export type ActionSheetProps = {
visible: boolean;
title: string;
options: Option[];
onSelect: (option: Option) => void;
onClose: () => void;
};
const ActionSheet: React.FC<ActionSheetProps> = ({
visible,
title,
options,
onSelect,
onClose,
}) => {
return (
<Modal
swipeDirection="down"
isVisible={visible}
style={styles.modal}
>
<TouchableWithoutFeedback
style={styles.overlay}
onPress={onClose}
>
<View style={styles.actionSheetContainer}>
<Text style={styles.actionSheetTitle}>{title}</Text>
{options.map((option, index) => (
<TouchableOpacity
key={index}
style={[
styles.actionSheetItem,
index === options.length - 1 && styles.lastItem,
]}
onPress={() => {
onSelect(option);
onClose();
}}
>
<Text style={styles.actionSheetText}>{option.label}</Text>
</TouchableOpacity>
))}
</View>
</TouchableWithoutFeedback>
</Modal>
);
};
const styles = StyleSheet.create({
modal: {
justifyContent: 'flex-end',
margin: 0,
},
overlay: {
flex: 1,
backgroundColor: 'rgba(0,0,0,0.4)',
justifyContent: 'flex-end',
},
actionSheetContainer: {
backgroundColor: '#fff',
borderTopLeftRadius: 16,
borderTopRightRadius: 16,
},
actionSheetTitle: {
fontSize: 16,
paddingVertical: 20,
fontWeight: "600",
fontFamily: "PingFang SC",
textAlign: "center",
textAlignVertical: 'center',
},
actionSheetItem: {
paddingVertical: 20,
borderBottomWidth: 1,
alignItems: 'center',
},
actionSheetText: {
fontSize: 14,
},
lastItem: {
borderBottomWidth: 0,
marginTop: 8,
backgroundColor: '#F7F7F7',
},
});
export default ActionSheet;
然后在业务代码中使用上面的自定义ActionSheet组件,如下所示:
const [actionSheetVisible, setActionSheetVisible] = useState(false);
const handleOptionSelect = (option: Option) => {
console.log(option.label)
// if (option.value !== 'cancel') {
// setActionSheetVisible(false);
// }
};
function renderActionSheet() {
const options: Option[] = [
{ label: '取消', value: 'cancel' },
];
return (<ActionSheet
visible={actionSheetVisible}
title="查看开通记录"
options={options}
onSelect={handleOptionSelect}
onClose={() => setActionSheetVisible(false)}
/>
)
}
最终的运行效果如下图: