选择用户组件
仿照微信做的一个选择用户的组件,逻辑很简单。支持单选多选
import React, { PureComponent } from 'react' import { View, StyleSheet, TouchableOpacity, Image, Text, TextInput, ScrollView, InteractionManager, FlatList, Dimensions } from 'react-native' import ChatConfig from './ChatConfig' const defaultUser = require('../images/avatar_contact.png') const checkedPhto = require('../images/checked.png'); const checkPhto = require('../images/check.png'); export default class SelectUserView extends PureComponent { constructor(props) { super(props); this.state = { pageIndex: 1, pageSize: 30, selectUser: {} }; } componentDidMount() { InteractionManager.runAfterInteractions(() => { this._loadFirstUserList(); }); } getSelectedUser(userInfo) { return this.state.selectUser[userInfo.uuId]; } getSelectedUserArray() { let userArray = []; for (let i in this.state.selectUser) { userArray.push(this.state.selectUser[i]); } return userArray; } getSelectedUserAll() { return this.state.selectUser; } setSelectedUser(userInfo) { if (this.props.isMulti) { if (this.state.selectUser[userInfo.uuId]) delete this.state.selectUser[userInfo.uuId]; else this.state.selectUser[userInfo.uuId] = userInfo; this.refs['searchUserTab'].renderListView(this.state.selectUser); this.refs['userListView'].refreshUserList(); } else { this.state.selectUser = {}; this.state.selectUser[userInfo.uuId] = userInfo; this.refs['searchUserTab'].renderListView(this.state.selectUser); } } _loadFirstUserList = () => { this.state.pageIndex = 1; //查询用户 }; _loadNextUserList() { this.state.pageIndex = this.state.pageIndex + 1; //查询用户 } render() { return ( <View style={{flex: 1, backgroundColor: '#fff'}}> <SearchUserTab loadFirstUserList={() => this._loadFirstUserList()} setSelectedUser={(userInfo) => this.setSelectedUser(userInfo)} ref="searchUserTab"/> <UserListView isMulti={this.props.isMulti} loadNextUserList={() => this._loadNextUserList()} loadFirstUserList={() => this._loadFirstUserList()} getSelectedUser={(userInfo) => this.getSelectedUser(userInfo)} setSelectedUser={(userInfo) => this.setSelectedUser(userInfo)} ref="userListView"/> </View> ); } } class SearchUserTab extends PureComponent { constructor(props) { super(props); this.state = { userList: {}, value: '' }; } renderListView(list) { this.setState({ userList: list }); } getSearchValue() { return this.state.value; } deleteSelected(userInfo) { this.props.setSelectedUser(userInfo); } _renderPhoto = (userInfo) => { if (userInfo.photo) return {uri: userInfo.photo}; else return defaultUser; }; _renderSelectedList() { this._selectedView = []; for (let i in this.state.userList) { this._selectedView.push(<TouchableOpacity key={i} activeOpacity={1} onPress={() => this.deleteSelected(this.state.userList[i])}><Image style={styles.selectedUserPhto} source={this._renderPhoto(this.state.userList[i])}/></TouchableOpacity>); } return this._selectedView; }; _onContentSizeChange = () => { this.refs["listUser"].scrollToEnd({animated: false}); } _renderSelectedUser() { if (Object.keys(this.state.userList).length == 0) return null; else return ( <View style={{ height: 45, width: Object.keys(this.state.userList).length > 5 ? (5 * 50) : (Object.keys(this.state.userList).length * 50) }}> <ScrollView onContentSizeChange={() => this._onContentSizeChange()} ref="listUser" style={{height: 45}} horizontal={true}> {this._renderSelectedList()} </ScrollView> </View> ); }; _onChangeText(event) { if (this.state.value == '' && event.nativeEvent.text == '' && Object.keys(this.state.userList).length != 0) { let lastUser; for (let i in this.state.userList) { lastUser = this.state.userList[i]; } this.props.setSelectedUser(lastUser); } this.setState({ value: event.nativeEvent.text }); console.log(event.nativeEvent.text); } render() { return ( <View style={styles.searchView}> {this._renderSelectedUser()} <TextInput ref="txt_message" placeholder={ChatConfig.SEARCH} returnKeyType="search" returnKeyLabel="search" style={styles.textInput} editable={true} keyboardType='default' autoCapitalize='none' autoCorrect={false} value={this.state.value} onSubmitEditing={() => this.props.loadFirstUserList()} onChange={(event) => this._onChangeText(event)} underlineColorAndroid='transparent' /> </View> ); } } class UserListView extends PureComponent { constructor(props) { super(props); this.state = { isRefreshing: true, dataList: [], isLastPage: false }; } setIsLastPage() { this.state.isLastPage = true; } setFirstList(list) { this.setState({ dataList: list, isRefreshing: false }); } setUserList(list) { this.setState({ dataList: this.state.dataList.concat(list) }); } _renderPhoto = (userInfo) => { if (userInfo.photo) return {uri: userInfo.photo}; else return defaultUser; }; _selectUser = (userInfo, index) => { this.props.setSelectedUser(userInfo); }; refreshUserList() { this.setState(this.state); } _renderCheckBox = (userInfo) => { if (this.props.isMulti) { return ( <View style={styles.userItemRight}> <Image style={styles.checkedImage} source={this.props.getSelectedUser(userInfo) ? checkedPhto : checkPhto}/> </View> ); } else return null; }; _renderItem = (item) => { let userInfo = item.item; return ( <TouchableOpacity activeOpacity={1} onPress={() => this._selectUser(userInfo, item.index)}> <View style={styles.userItem}> <View style={styles.userItemLeft}> <Image style={styles.userPhoto} source={this._renderPhoto(userInfo)}/> </View> <View style={styles.userItemCenter}> <Text numberOfLines={1}>{userInfo.userName}</Text> </View> {this._renderCheckBox(userInfo)} </View> </TouchableOpacity> ); }; _separator = () => { return <View style={styles.separator}/>; }; _onEndReached = () => { if (!this.state.isLastPage && this.state.dataList.length != 0) this.props.loadNextUserList(); }; _onRefresh = () => { this.setState({ isRefreshing: true }); this.props.loadFirstUserList(); }; _keyExtractor = (item, index) => item.uuId; render() { return ( <FlatList refreshing={this.state.isRefreshing} onRefresh={() => this._onRefresh()} ItemSeparatorComponent={this._separator} ref="listMessage" extraData={this.state} keyExtractor={this._keyExtractor} data={this.state.dataList} onEndReached={this._onEndReached} renderItem={this._renderItem}/> ); } } const styles = StyleSheet.create({ searchView: { height: 60, paddingLeft: 10, paddingRight: 10, borderColor: '#efeff4', borderBottomWidth: 1, flexDirection: 'row', alignItems: 'center' }, textInput: { flex: 1, fontSize: 15, borderWidth: 0, height: 45, textAlignVertical: 'center' }, separator: { backgroundColor: '#efeff4', height: 1 }, userItem: { height: 60, flexDirection: 'row', backgroundColor: '#fff', paddingLeft: 10, paddingRight: 10, }, userPhoto: { width: 45, height: 45 }, selectedUserPhto: { width: 45, height: 45, marginRight: 5 }, userItemLeft: { justifyContent: 'center', width: 45 }, userItemCenter: { marginLeft: 10, justifyContent: 'center', flex: 1 }, userItemRight: { width: 40, alignItems: 'center', justifyContent: 'center' }, checkedImage: { width: 20, height: 20 } });