下面是关于"react-native 封装选择弹出框示例(试用ios&android)"的完整攻略。
1. 简介
本篇攻略将介绍如何封装一个React Native的选择弹出框组件,并提供两个具体实例以及对应的完整代码。
2. 需求分析
在实际的开发过程中,选择弹出框是一个经常使用的UI组件。因此,我们需要封装这个组件,使得以后在开发中可以方便地使用它。
以下是选择弹出框的需求分析:
- 组件需要在ios和android下都能正常工作;
- 组件需要支持单选和多选两种模式;
- 组件需要支持传入选择项的数据源;
- 组件需要支持外部自定义布局;
- 组件需要支持选择完成后的回调函数。
根据以上需求,我们可以开始着手实现这个组件。
3. 实现过程
3.1 创建选择弹出框组件SelectModal
我们可以通过继承官方的Modal组件来实现选择弹出框组件。首先,我们需要在项目中创建一个名为SelectModal的文件夹,并在其中创建index.js文件和styles.js文件,代码如下:
// index.js
import React, {Component} from 'react';
import {View, Text, Button, Modal, TouchableOpacity, StyleSheet} from 'react-native';
class SelectModal extends Component {
constructor(props) {
super(props);
}
render() {
return <View></View>;
}
}
export default SelectModal;
// styles.js
import {StyleSheet} from 'react-native';
export default StyleSheet.create({
container: {
flex: 1,
},
});
注意,由于我们需要用到Modal和TouchableOpacity等官方组件,因此在文件开头需要对它们进行引入。
接下来,我们需要在SelectModal类中实现选择弹出框组件的主要功能。这里仅给出完整代码,详细讲解将放在后面的示例中。最终,SelectModal组件的代码如下:
// index.js
import React, {Component} from 'react';
import {
View,
Text,
Button,
Modal,
TouchableOpacity,
StyleSheet,
} from 'react-native';
class SelectModal extends Component {
constructor(props) {
super(props);
this.state = {
visible: false, // 是否显示
selectMode: 'single', // 'single' / 'multiple'
selectedIndex: [], // 已选择的选项索引数组
};
}
setSelectedIndex(index) {
let {selectMode, selectedIndex} = this.state;
if (selectMode === 'single') {
// 单选
this.setState({
visible: false,
selectedIndex: [index],
});
} else {
// 多选
selectedIndex = selectedIndex.slice();
if (selectedIndex.includes(index)) {
// 当前项已经被选中,删除
selectedIndex.splice(selectedIndex.indexOf(index), 1);
} else {
// 当前项未被选中,添加
selectedIndex.push(index);
}
this.setState({
visible: false,
selectedIndex,
});
}
// 调用外部回调函数
if (this.props.onSelect) {
setTimeout(() => {
this.props.onSelect(selectedIndex);
}, 100);
}
}
render() {
let {visible, selectMode, selectedIndex} = this.state;
let {data, renderItem, renderItemText, title, cancelText, confirmText} =
this.props;
return (
<Modal visible={visible} transparent={true} animationType="fade">
<TouchableOpacity
activeOpacity={1}
style={styles.container}
onPress={() => {
this.setState({
visible: false,
});
}}>
<View style={styles.content}>
<View style={styles.titleContainer}>
<Text style={styles.titleText}>{title}</Text>
</View>
<View style={styles.itemContainer}>
{data.map((item, index) => {
let selected = selectedIndex.includes(index);
let renderItemUI = renderItem
? renderItem(item, selected)
: null;
if (!renderItemUI) {
renderItemUI = (
<View
style={[
styles.item,
selected ? styles.selectedItem : null,
]}
key={index}>
<Text style={styles.itemText}>{item}</Text>
{selected ? (
<View style={styles.selectedIcon} />
) : null}
</View>
);
}
return (
<TouchableOpacity
activeOpacity={1}
onPress={() => {
this.setSelectedIndex(index);
}}
key={index}>
{renderItemUI}
</TouchableOpacity>
);
})}
</View>
<View style={styles.btnContainer}>
<TouchableOpacity
activeOpacity={0.8}
style={styles.cancelBtn}
onPress={() => {
this.setState({
visible: false,
});
}}>
<Text style={styles.btnText}>{cancelText}</Text>
</TouchableOpacity>
<TouchableOpacity
activeOpacity={0.8}
style={styles.confirmBtn}
onPress={() => {
this.setSelectedIndex(selectedIndex);
}}>
<Text style={styles.btnText}>{confirmText}</Text>
</TouchableOpacity>
</View>
</View>
</TouchableOpacity>
</Modal>
);
}
}
SelectModal.defaultProps = {
data: [], // 数据源
renderItem: null, // 渲染自定义选项UI的函数
renderItemText: null, // 渲染选项文本的函数
title: '', // 标题
cancelText: '取消', // 取消按钮文本
confirmText: '确定', // 确定按钮文本
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'rgba(0,0,0,0.5)',
justifyContent: 'center',
alignItems: 'center',
},
content: {
backgroundColor: 'white',
borderRadius: 10,
width: '80%',
},
titleContainer: {
height: 50,
justifyContent: 'center',
alignItems: 'center',
borderBottomWidth: 1,
borderBottomColor: '#F0F0F0',
},
titleText: {
fontSize: 18,
fontWeight: 'bold',
},
itemContainer: {
maxHeight: 300,
},
item: {
padding: 10,
},
itemText: {
fontSize: 16,
color: '#333',
},
selectedItem: {
backgroundColor: '#F0F0F0',
},
selectedIcon: {
position: 'absolute',
top: 10,
right: 10,
width: 12,
height: 12,
borderRadius: 6,
backgroundColor: '#3F51B5',
},
btnContainer: {
borderTopWidth: 1,
borderTopColor: '#F0F0F0',
flexDirection: 'row',
justifyContent: 'flex-end',
},
cancelBtn: {
width: 80,
height: 50,
justifyContent: 'center',
paddingLeft: 10,
paddingRight: 10,
},
confirmBtn: {
width: 80,
height: 50,
justifyContent: 'center',
paddingLeft: 10,
paddingRight: 10,
},
btnText: {
fontSize: 16,
color: '#3F51B5',
},
});
export default SelectModal;
可以看到,SelectModal组件的代码已经完成了全部实现,包括Modal的显示和隐藏、单选和多选功能、自定义布局、回调函数等。
3.2 使用SelectModal组件
下面我们将分别给出两个具体的使用示例。
3.2.1 示例一:总统选举
在这个示例中,我们将使用SelectModal组件来演示一个总统选举的投票流程。假设投票人可以选择一位总统候选人进行投票,投票结果将在弹出框标题上显示。完整代码如下:
import React, {Component} from 'react';
import {View, Text, TouchableOpacity} from 'react-native';
import SelectModal from './SelectModal';
class Example1 extends Component {
constructor(props) {
super(props);
this.state = {
selectedIndex: [], // 已选择的候选人索引数组
};
}
render() {
let {selectedIndex} = this.state;
return (
<View style={{flex: 1}}>
<TouchableOpacity
activeOpacity={0.8}
onPress={() => {
this.setState({
modalVisible: true,
});
}}>
<View style={{height: 50, justifyContent: 'center'}}>
<Text>
{selectedIndex.length > 0
? '你已经选择了' + (selectedIndex[0] + 1) + '号候选人'
: '请选择一位总统候选人'}
</Text>
</View>
</TouchableOpacity>
<SelectModal
visible={this.state.modalVisible}
data={['候选人1', '候选人2', '候选人3']}
onSelect={(selectedIndex) => {
this.setState({
modalVisible: false,
selectedIndex,
});
}}
title="总统选举"
cancelButtonText="取消"
confirmButtonText="确定"
/>
</View>
);
}
}
export default Example1;
以上代码实现了一个简单的投票系统,当点击文本框时,选择弹出框组件将显示,用户可以选择喜欢的候选人进行投票。投票完成后,选择弹出框组件会自动隐藏,并将选择的结果显示在文本框的文本上。代码中的data属性定义了三个候选人,分别对应了三个投票选项。
3.2.2 示例二:星座配对
在这个示例中,我们将使用SelectModal组件来演示一个星座配对的小游戏。假设用户可以从两个弹出框中选择自己和匹配对象的星座,系统将自动根据选择的星座生成配对结果。完整代码如下:
import React, {Component} from 'react';
import {View, Text, TouchableOpacity} from 'react-native';
import SelectModal from './SelectModal';
class Example2 extends Component {
constructor(props) {
super(props);
this.state = {
selectedStarIndex1: [], // 已选择的星座1索引数组
selectedStarIndex2: [], // 已选择的星座2索引数组
};
}
getResult() {
let starNames = [
'白羊座',
'金牛座',
'双子座',
'巨蟹座',
'狮子座',
'处女座',
'天秤座',
'天蝎座',
'射手座',
'摩羯座',
'水瓶座',
'双鱼座',
];
let getResultByStars = (star1, star2) => {
let index1 = starNames.indexOf(star1);
let index2 = starNames.indexOf(star2);
let resultIndex = (index1 + index2) % 12;
return starNames[resultIndex];
};
let {selectedStarIndex1, selectedStarIndex2} = this.state;
let star1 =
selectedStarIndex1.length > 0 ? starNames[selectedStarIndex1[0]] : '';
let star2 =
selectedStarIndex2.length > 0 ? starNames[selectedStarIndex2[0]] : '';
let result = getResultByStars(star1, star2);
return result;
}
render() {
let result = this.getResult();
return (
<View style={{flex: 1}}>
<TouchableOpacity
activeOpacity={0.8}
onPress={() => {
this.setState({
modalVisible1: true,
});
}}>
<View style={{height: 50, justifyContent: 'center'}}>
<Text>
{this.state.selectedStarIndex1.length > 0
? '你选择的星座是' +
[
'白羊座',
'金牛座',
'双子座',
'巨蟹座',
'狮子座',
'处女座',
'天秤座',
'天蝎座',
'射手座',
'摩羯座',
'水瓶座',
'双鱼座',
][this.state.selectedStarIndex1[0]]
: '请选择自己的星座'}
</Text>
</View>
</TouchableOpacity>
<TouchableOpacity
activeOpacity={0.8}
onPress={() => {
this.setState({
modalVisible2: true,
});
}}>
<View style={{height: 50, justifyContent: 'center'}}>
<Text>
{this.state.selectedStarIndex2.length > 0
? '你选择的星座是' +
[
'白羊座',
'金牛座',
'双子座',
'巨蟹座',
'狮子座',
'处女座',
'天秤座',
'天蝎座',
'射手座',
'摩羯座',
'水瓶座',
'双鱼座',
][this.state.selectedStarIndex2[0]]
: '请选择另一半的星座'}
</Text>
</View>
</TouchableOpacity>
{this.state.selectedStarIndex1.length > 0 &&
this.state.selectedStarIndex2.length > 0 ? (
<View style={{flex: 1, justifyContent: 'center'}}>
<Text style={{fontSize: 24}}>你们的星座配对结果是</Text>
<Text style={{fontSize: 36}}>{result}</Text>
</View>
) : (
<View style={{height: 300}}></View>
)}
<SelectModal
visible={this.state.modalVisible1}
data={[
'白羊座',
'金牛座',
'双子座',
'巨蟹座',
'狮子座',
'处女座',
'天秤座',
'天蝎座',
'射手座',
'摩羯座',
'水瓶座',
'双鱼座',
]}
onSelect={(selectedStarIndex1) => {
this.setState({
modalVisible1: false,
selectedStarIndex1,
});
}}
title="请选择你的星座"
cancelButtonText="取消"
confirmButtonText="确定"
/>
<SelectModal
visible={this.state.modalVisible2}
data={[
'白羊座',
'金牛座',
'双子座',
'巨蟹座',
'狮子座',
'处女座',
'天秤座',
'天蝎座',
'射手座',
'摩羯座',
'水瓶座',
'双鱼座',
]}
onSelect={(selectedStarIndex2) => {
this.setState({
modalVisible2: false,
selectedStarIndex2,
});
}}
title="请选择另一半的星座"
cancelButtonText="取消"
confirmButtonText="确定"
/>
</View>
);
}
}
export default Example2;
以上代码实现了一个简单的星座配对小游戏,用户可以在两个弹出框中选择自己和另一半的星座。当两个选择框都有选择时,程序会自动根据选定的星座计算配对结果,并将结果显示在页面下方。在代码中,getResult函数即为计算配对结果的函数。
4. 结语
通过以上两个示例,我们可以看到如何封装一个选择弹出框组件,并对其进行简单的定制和使用。在实际的开发过程中,我们可以根据具体需求对组件代码进行修改,从而得到一个更符合自己需求的组件。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:react-native 封装选择弹出框示例(试用ios&android) - Python技术站