看着那些选择组件,不能满足开发项目的需求,还是自己编写一个
自定义的模态框选择组件
功能说明
同一个组件实现如下功能
0、出现动画效果
1、多选:可以实现多选的功能
2、单选:可以实现单项选择
3、存在默认值情况处理
**
* 模态选择框
*
* props:
* data: [{id:1,display: '111111',}],//数据格式 id 和display描述
* mult: true|false 是否多选
* dataKey:{id:"_id",display:"text"} //自定义索引key
* search 是否可以搜索/本地过滤 默认true
* title 提示标题 默认 请选择
* defaultChecked; // 1 | "1" | {id:1} | {index:1} | [...]
* onChange (item)=>
* //个性化定制 每一个item点击时调用
* //style={UISelectModal.style.borderRadius}
//rootStyle={{width:100,alignSelf: 'flex-end',}}
* activeColor 选中颜色
*
* RenderItem:(item,isActive)=> //自定义 item样式
*
* ref ----绑定ref 用来获取选中的值 this.refs.定义的ref.getVlue();
* func
* getValue: return [] | {}
*/
import React,{Component} from 'react';
import {
Animated,
View,
TextInput,
Image,
TouchableOpacity,
StyleSheet,
Text,
Button,
ImageBackground,
Modal,
FlatList,
Platform,
ScrollView,
TouchableHighlight} from 'react-native';
export default class UISelectModal extends Component{
constructor(props){
super(props);
this.state={
searchData:null,
show:false,
fadeAnim: new Animated.Value(100),
checkedState:{}, //记录选项选中状态
data:this.props.data || [],
}
}
componentDidMount(){
this.initDefaultChecked(this.props.defaultChecked);
}
/**初始化默认选中 */
isInitDefaultChecked=false;
initDefaultChecked=(defaultChecked,target=0)=>{
if(this.isInitDefaultChecked){
return false;
}
let type = typeof(defaultChecked);
if(type === "string" || type === "number"){
this.setCheckedState(defaultChecked,true);
}else if(defaultChecked instanceof Array){
for(let i=0;i{
return this.state.checkedState;
}
setCheckedState=(key,state)=>{
let c = this.getCheckedStateConfig();
c[key] = state;
}
getCheckedState=(key=null)=>{
let c = this.getCheckedStateConfig();
if(key){
return !!c[key];
}
let actives = [];
for(let key in c){
let ac = !!c[key];
if(ac)actives.push(key);
}
return actives;
}
clearAllCheckedState=()=>{
this.state.checkedState = {};
}
switchCheckedState=(key)=>{
let old = this.getCheckedState(key);
let active = !old;
this.setCheckedState(key,active);
return active;
}
updateCheckedState=()=>{
this.setState({checkedState:this.getCheckedStateConfig()});
}
getActiveItem=()=>{
let cs = this.getCheckedState();
let ds = this.state.data;
let activeItems = [];
for(let i=0;ithis.getItemID(item) == activeID);
if(activeIndex<=-1)continue;
let activeItem = ds[activeIndex];
activeItems.push(activeItem);
}
return activeItems;
}
getItemID=(item)=>{
const key = this.props.dataKey||{};
return item[key["id"]];
}
getItemDiaplay=(item)=>{
const key = this.props.dataKey||{};
return item[key["display"]];
}
getValue(){
let activeItem = this.getActiveItem();
let mult = this.props.mult;
if(!mult){
return activeItem[0];
}
return activeItem;
}
componentWillReceiveProps(nextProps){
let nextData = nextProps.data;
this.setState(({data})=>{
return {data:nextData};
},()=>{
this.initDefaultChecked(nextProps.defaultChecked);
});
}
switch=(state = null)=>{
let isShow = !this.state.show;
this.setState({show:isShow,searchData:null},()=>{
this.state.fadeAnim.setValue(0);
this.animated = Animated.spring(
this.state.fadeAnim,
{
toValue:100,
duration:300,
}
).start();
})
}
componentWillUnmount(){
if(this.state.show){
this.setState({show:false});
}
}
getTitleDisplay(){
let activeItems = this.getActiveItem();
let names = activeItems.map((item)=>this.getItemDiaplay(item));
return names.length>0?
{names.join(",")}
:
{this.props.title}
}
search(e) {
if(!e){
this.setState({searchData:null});
return;
};
let list = this.state.data;
const key = this.props.dataKey||{};
let newList = list.filter((item)=>{
return this.getItemDiaplay(item).indexOf(e)>-1;
});
this.setState({searchData:newList});
}
checkItem=(item)=>{
let mult = this.props.mult;
let id = this.getItemID(item);
let active = this.getCheckedState(id);
let nextActive = !active;
if(nextActive){
let checkedStates = this.getCheckedState();
if(checkedStates && checkedStates.length){
if(typeof mult === "number"){
if(checkedStates.length>=mult){
return alert("最多选择"+mult+"项");
}
}else if(!mult){
this.clearAllCheckedState();
}
}
}
this.setCheckedState(id,nextActive);
this.updateCheckedState();
let onChange = this.props.onChange;
if(typeof(onChange) === "function"){
onChange(item,this.getActiveItem());
}
//不是多选选择完马上关闭
if(!mult)this.switch();
}
render() {
const spinOpacity = this.state.fadeAnim.interpolate({
inputRange: [0, 100],
outputRange: [0,1]
});
const spinRotate = this.state.fadeAnim.interpolate({
inputRange: [0, 100],
outputRange: this.state.show?["0deg","180deg"]:['180deg', '0deg']
});
const spinTop = this.state.fadeAnim.interpolate({
inputRange: [0, 100],
outputRange:[140,0]
});
const key = this.props.dataKey||{};
let dataList = this.state.searchData || this.state.data || [];
let isSearch = this.props.search;
let RenderItem = this.props.RenderItem;
let activeColor = this.props.activeColor;
return (
{ this.getTitleDisplay()}
{
(this.state.show) &&
{this.props.title}
{
dataList.length<=0?
{(this.state.searchData && this.state.searchData.length<1)?"没有搜索到数据":"暂无数据"}
:
{
dataList.map((item,index)=>{
let id = this.getItemID(item);
let display = this.getItemDiaplay(item);
let active = this.getCheckedState(id);
return(
typeof(RenderItem) === "function"?
this.checkItem(item)}>
{
RenderItem(item,active)
}
:
this.checkItem(item)}>
{
{display}
}
);
})
}
}
{
(dataList.length>5 && isSearch) &&
this.search(e)}
/>
}
}
)
}
}
在此插件基础上扩展---复选框
{
//data {id:1,display:'选项1'}
//获取选择的内容
this.refs.selects.getValue();
}}
defaultChecked={{index:0}}
rootStyle={{marginHorizontal:10,}}
style={{margin:4}}
mult={true} />
/**
* 单选复选框
* RenderItem
*/
export class UISelect extends UISelectModal{
static defaultProps = {
dataKey:{id:"id",display:"display"},
mult:false,
activeColor:themeConfig.mainBgColor,
rootStyle:{},
}
styles = StyleSheet.create({
root:{
flexDirection:"row",
flexWrap:"wrap"
},
item:{
paddingHorizontal:10,
paddingVertical:4,
borderColor:"#f7f7f7",
borderWidth:1,
borderRadius:20,
margin:5,
}
});
render(){
let data = this.state.data;
let RenderItem = this.props.RenderItem;
const styles = this.styles;
const activeColor = this.props.activeColor;
return (
{
(data && data.length)?
data.map((item,index)=>{
let id = this.getItemID(item);
let display = this.getItemDiaplay(item);
let active = this.getCheckedState(id);
let color = (active?activeColor:"#666666");
return(
typeof(RenderItem) === "function"?
this.checkItem(item)}>
{
RenderItem(item,active)
}
:
this.checkItem(item)}>
{display}
);
}):false
}
)
};
}