TouchableOpacity和TextInput在位于以下位置的视图内不起作用:“绝对”

时间:2020-09-14 11:42:43

标签: react-native scrollview absolute

我有一个自定义下拉菜单,其中下拉视图绝对定位。当组件直接位于滚动视图内部时,我将无法执行文本输入和可触摸操作。

自定义组件代码:

import React, { Component } from 'react';
import { View, Text, StyleSheet, TouchableOpacity, ScrollView, TextInput } from 'react-native';
import Icon_Feather from 'react-native-vector-icons/Feather';
import Icon_MaterialIcons from 'react-native-vector-icons/MaterialIcons';
import PropTypes from 'prop-types';
import _ from 'lodash';

let dropDownData = []

class MultiSelectDropdown extends Component {

    constructor(props) {
        super(props);

        this.state = {
            isVisible: false,
            data: [],
            searchData: [],
            selectedData: [],
            // selectAllStatus: false,
            searchableText: null,
            defaultSelectedValues: ''
        }
    }

    UNSAFE_componentWillReceiveProps = async (props) => {
        await this.setState({
            data: props.data,
            defaultSelectedValues: props.selectedData != undefined ? props.selectedData : [],
            isVisible: props.isVisible
        })
        // alert(this.state.data)
        await this.formatReceivedData()
    }

    formatReceivedData = async () => {
        var pushedData = []
        let tempData = JSON.parse(JSON.stringify(this.state.data))
        tempData.forEach(element => {
            let obj = element
            Object.assign(obj, { selected: false })
            pushedData.push(obj)
        });

        await this.setState({
            selectedData: pushedData,
            searchData: pushedData,
        })

        if (this.state.defaultSelectedValues.length > 0)
            await this.checkDefaultValues();
    }

    checkDefaultValues = async () => {
        this.state.data.forEach((ele1, index1) => {
            this.state.defaultSelectedValues.forEach((ele2, index2) => {
                if (_.isEqual(ele1, ele2)) {
                    this.state.selectedData[index1].selected = true
                    this.setState({
                        selectedData: this.state.selectedData
                    })
                }
            });
        });
    }

    getLayout(layout) {
        this.setState({
            top: layout.height - 1
        });
    }

    toggle() {
        // this.setState({
        //     isVisible: ! this.state.isVisible,
        // }, () => {
        //     const isVisible = this.state.isVisible;

        //     // if (isVisible) {
        //  //  this.props.onOpen();
        //  // } else {
        //  //  this.props.onClose();
        //  // }
        // });
        this.setState({
            isVisible: !this.state.isVisible,
        })
    }

    selectItem = async (data, index) => {
        var tempSelectedData = this.state.selectedData

        if (tempSelectedData[index].selected == false)
            tempSelectedData[index].selected = true
        else
            tempSelectedData[index].selected = false

        var truePropertyData = tempSelectedData.filter((item) => {
            return item.selected != false
        })

        if (truePropertyData.length > this.props.maxItemsToSelect) {
            // max
            tempSelectedData[index].selected = false;
            var truePropertyData1 = tempSelectedData.filter((item) => {
                return item.selected!= false
            })
            this.removeExtraAddedProperty(truePropertyData1, index);
        } else {
            this.setState({
                selectedData: tempSelectedData,
                // selectAllStatus: false
            })
            this.removeExtraAddedProperty(truePropertyData, index);
        }

    }

    getSelectedItemCount = () => {
        var truePropertyData = this.state.selectedData.filter((item) => {
            return item.selected!= false
        })
        return truePropertyData;
    }

    getLabelDisplayText = () => {
        let count = this.getSelectedItemCount().length;
        return this.props.multipleDataSelectedText.replace('%d', count);
    }

    selectAll = async () => {
        var tempSelectedData = JSON.parse(JSON.stringify(this.state.selectedData))

        var status = await this.selectAllOrUnselect()

        // if (this.state.selectAllStatus) {
        if (status) {
            tempSelectedData.forEach((ele, i) => {
                tempSelectedData[i].selected= false
            });
            this.setState({
                selectedData: tempSelectedData,
                // selectAllStatus: false
            })

            var truePropertyData = tempSelectedData.filter((item) => {
                return item.selected!= false
            })
            this.removeExtraAddedProperty(truePropertyData, 0)

        } else {
            tempSelectedData.forEach((ele, i) => {
                tempSelectedData[i].selected= true
            });
            this.setState({
                selectedData: tempSelectedData,
                // selectAllStatus: true
            })
            this.removeExtraAddedProperty(this.state.selectedData, 0)
        }

    }

    removeExtraAddedProperty = (truePropertyData, index) => {
        let tempTruePropertyData = JSON.parse(JSON.stringify(truePropertyData))
        var actualData = []
        if (tempTruePropertyData.length > 0) {
            tempTruePropertyData.forEach(element => {
                var obj = element
                delete obj['selected']
                actualData.push(obj)
            });
        } else
            this.props.onItemChange(truePropertyData, index)

        this.props.onItemChange(actualData, index)
    }

    selectAllOrUnselect = () => {
        var returnStatus;
        var trueFilteredData = this.state.selectedData.filter((item, i) => {
            return item.selected == true
        })

        if (trueFilteredData.length == this.state.selectedData.length)
            returnStatus = true
        else
            returnStatus = false

        return returnStatus;
    }

    updateSearch = async (text) => {
        await this.setState({
            searchableText: text
        })

        let toSearch = (this.state.searchableText).toLowerCase();
        let result = this.state.data.filter(o => o[this.props.displayLabel].toLowerCase().includes(toSearch));

        await this.setState({
            searchData: result
        })
    }

    render() {
        return (
            <View style={[this.props.containerStyle, {
                ...(Platform.OS !== 'android' && {
                    zIndex: this.props.zIndex
                })
            }]}>
                <TouchableOpacity
                    onLayout={(event) => this.getLayout(event.nativeEvent.layout)}
                    onPress={() => this.toggle()}
                    activeOpacity={1}
                    style={[
                        styles.dropDown,
                        this.props.style,
                        this.state.isVisible && styles.noBottomRadius, {
                            flexDirection: 'row', flex: 1
                        }
                    ]}
                >
                    <View style={[styles.dropDownDisplay]}>
                        {/* <Text style={[this.props.labelStyle, { flex: 1, marginRight: 5 }]}> */}
                        {/* {this.props.placeHolder} {this.getSelectedItemCount().length} */}
                        {/* {this.getSelectedItemCount().length > 0 ?
                                'Under Test'
                            :
                                JSON.stringify(this.state.placeHolder)
                            } */}
                        {/* </Text> */}
                        {this.getSelectedItemCount().length > 0 ?
                            <Text style={[this.props.labelStyle, { flex: 1, marginRight: 5 }]}>
                                {this.getLabelDisplayText()}
                            </Text>
                            :
                            <Text style={[this.props.labelStyle, { flex: 1, marginRight: 5 }]}>
                                {this.props.placeHolder} {JSON.stringify(this.state.isVisible)}
                            </Text>
                        }
                    </View>

                    <View style={[styles.arrow]}>
                        {!this.state.isVisible ?
                            <Icon_Feather name="chevron-down" size={15} color={'black'} />
                            :
                            <Icon_Feather name="chevron-up" size={15} color={'black'} />
                        }
                    </View>

                </TouchableOpacity>

                <View style={[
                    styles.dropDown,
                    styles.dropDownBox,
                    this.props.dropDownStyle,
                    !this.state.isVisible && styles.hidden, {
                        top: this.state.top,
                        maxHeight: this.props.dropDownMaxHeight,
                        zIndex: this.props.zIndex
                    }
                ]}>

                    {/* Search Text */}
                    <View style={{ width: '100%', flexDirection: 'row' }}>
                        <TextInput
                            style={[styles.input, this.props.searchableStyle]}
                            defaultValue={this.state.searchableText}
                            placeholder={this.props.searchablePlaceholder}
                            onChangeText={(text) => this.updateSearch(text)}
                        />
                    </View>

                    <ScrollView style={{ width: '100%' }} nestedScrollEnabled={true}>
                        {this.state.searchData.length > 0 ? this.state.searchData.map((item, index) => (
                            <View key={index}>
                                <TouchableOpacity
                                    style={[styles.dropDownItem, this.props.itemStyle]}
                                    onPress={() => this.selectItem(item, index)}
                                >
                                    <View style={{ flexDirection: 'row' }}>
                                        <View style={{ paddingRight: 5 }}>
                                            {(this.state.selectedData[index] != undefined && this.state.selectedData[index].selected == true) ?
                                                <Icon_MaterialIcons name={'check-box'} size={22} color={'black'} />
                                                :
                                                <Icon_MaterialIcons name={'check-box-outline-blank'} size={22} color={'black'} />
                                            }
                                        </View>
                                        <View style={{ justifyContent: 'center', alignItems: 'center' }}>
                                            <Text style={[this.props.labelStyle]}>
                                                {item[this.props.displayLabel]}
                                            </Text>
                                        </View>
                                    </View>
                                </TouchableOpacity>
                            </View>
                        ))
                            :
                            <Text>
                                Not Found
                            </Text>
                        }
                    </ScrollView>

                </View>
            </View >
        );
    }
}

MultiSelectDropdown.defaultProps = {
    containerStyle: {},
    style: {},
    zIndex: 5000,
    placeHolder: 'Select an option',
    labelStyle: {},
    dropDownStyle: {},
    dropDownMaxHeight: 250,
    itemStyle: {},
    displayLabel: '',
    searchableStyle: {},
    searchablePlaceholder: 'Search',
    multipleDataSelectedText: '%d items have been selected',
    data: PropTypes.array.isRequired,
    maxItemsToSelect: '',
    isVisible: false,
    selectAllText: 'Select All',
    unselectAllText: 'Un-Select All'
}

MultiSelectDropdown.propTypes = {
    containerStyle: PropTypes.object,
    style: PropTypes.object,
    zIndex: PropTypes.number,
    placeHolder: PropTypes.string,
    labelStyle: PropTypes.object,
    dropDownStyle: PropTypes.object,
    dropDownMaxHeight: PropTypes.number,
    itemStyle: PropTypes.object,
    displayLabel: PropTypes.string,
    searchableStyle: PropTypes.object,
    isVisible: PropTypes.bool,
    searchablePlaceholder: PropTypes.string,
    selectedData: PropTypes.any,
    multipleDataSelectedText: PropTypes.string,
    maxItemsToSelect: PropTypes.string,
    selectAllText: PropTypes.string,
    unselectAllText: PropTypes.string
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        backgroundColor: 'white',
    },
    noBottomRadius: {
        borderBottomLeftRadius: 0,
        borderBottomRightRadius: 0,
    },
    dropDown: {
        paddingHorizontal: 10,
        paddingVertical: 5,
        backgroundColor: '#fff',
        borderTopRightRadius: 5,
        borderTopLeftRadius: 5,
        borderBottomRightRadius: 5,
        borderBottomLeftRadius: 5,
        borderWidth: 1,
        borderColor: '#dfdfdf',
    },
    dropDownDisplay: {
        flexDirection: 'row',
        alignItems: 'center',
        borderTopRightRadius: 0,
        borderBottomRightRadius: 0,
        flexGrow: 1
    },
    arrow: {
        flexDirection: 'row',
        justifyContent: 'center',
        alignItems: 'center',
        textAlign: 'center',
        paddingVertical: 8,
        borderTopLeftRadius: 0,
        borderBottomLeftRadius: 0,
    },
    dropDownBox: {
        borderTopLeftRadius: 0,
        borderTopRightRadius: 0,
        alignItems: 'center',
        justifyContent: 'center',
        textAlign: 'center',
        position: 'absolute',
        width: '100%',
        zIndex: 1
    },
    hidden: {
        position: 'relative',
        display: 'none',
        borderWidth: 0
    },
    dropDownItem: {
        paddingVertical: 8,
        width: '100%',
        justifyContent: 'center'
    },
    input: {
        flex: 1,
        borderColor: '#dfdfdf',
        borderBottomWidth: 1,
        paddingHorizontal: 0,
        paddingVertical: 8,
        marginBottom: 2,
    },
});

export default MultiSelectDropdown;

上面的组件在视图中使用时可以正常工作,但是当将其放置在模式中时则无法工作。即我无法执行触摸和文本输入操作。

0 个答案:

没有答案