admin管理员组

文章数量:1289868

I'm having an issue with scrolling in lists that are in modals ever since upgrading to the latest React-Native version (0.55.4). In this case it is a Flatlist

The Flatlist with the problem is inside a modal, which is in another modal that is rendered as a footer ponent on another Flatlist (it is an add button).

Please help! Thank you

Code:

Flatlist Footer Component (Add Button):

@observer
class AddButton extends Component {
    @observable visible = false;

    constructor(props) {
        super(props);
        this.state = {
            mergeName: '',
            coin: undefined
        };
    }
    show = () => {
        this.visible = true;
    };

    hide = () => {
        this.visible = false;
    };

    render() {

        return (
            <View>
                <Button
                    primary
                    onPress={() => {
                        this.show();
                    }}
                    title={'add'}
                    style={{
                        width: '50%',
                        alignSelf: 'center',
                        marginVertical: 16
                    }}
                />
                <Modal
                    visible={this.visible}
                    animationType='slide'
                    onRequestClose={this.hide}
                >
                    <Screen>
                        <View style={{ padding: 5, backgroundColor: '#0003' }}>
                            <TouchableOpacity
                                style={{
                                    width: '50%',
                                    height: 40,
                                    paddingHorizontal: 10,
                                    justifyContent: 'center'
                                }}
                                onPress={this.hide}
                            >
                                <Text style={{ color: '#fff' }}>
                                    {'cancel'}
                                </Text>
                            </TouchableOpacity>
                        </View>

                        <View>
                            <Row>
                                <RowLabel>{'coin'}:</RowLabel>
                                <Selector
                                    force
                                    ref={'mySelector'}
                                    value={this.coin}
                                    onSelect={coin => {
                                        this.handleSelect();
                                    }}
                                    data={allCoins}
                                />
                            </Row>
                            <Button
                                primary
                                onPress={this.handleSubmit}
                                title={this.props.i18n.'add'}
                                style={{
                                    width: '50%',
                                    alignSelf: 'center',
                                    marginVertical: 16
                                }}
                            />
                        </View>
                    </Screen>
                </Modal>
            </View>
        );
    }
}

export default AddButton;

const contentStyle = {
    flex: 1,
    backgroundColor: '#0003',
    paddingLeft: 10,
    borderRadius: 3
};

const Row = ({ style, ...rest }) => (
    <View
        style={[
            {
                height: 60,
                flexDirection: 'row',
                alignItems: 'center',
                padding: 10,
                marginRight: 10
            },
            style
        ]}
        {...rest}
    />
);

const RowLabel = props => (
    <Text style={{ width: 80, color: '#ccc' }} {...props} />
);

const Input = (props: TextInputProperties) => (
    <View style={contentStyle}>
        <TextInput
            placeholderTextColor='#fff3'
            style={{ color: '#ccc', flex: 1, fontSize: 14 }}
            {...props}
        />
    </View>
);

Problematic Flatlist in Modal Component (Selector):

@observer
class Selector extends Component {
    @observable value = '';
    @observable visible = false;
    constructor(props) {
        super(props);
        if (props.modify) {
            this.selectValue();
        }
    }

    selectValue = () => {
        this.value = this.props.value;
    };

    show = () => {
        if (this.props.force) this.visible = true;
        if (!this.props.coin) return;
        this.visible = true;
    };

    hide = () => {
        this.filterText = '';
        this.visible = false;
    };

    handleSelect = item => {
        this.value = item;
        if (typeof this.props.onSelect === 'function') {
            this.props.onSelect(item);
        }
        this.hide();
    };

    ponentWillReceiveProps(nextProps) {
        if (nextProps.value !== this.value) {
            this.value = nextProps.value || '';
        }
    }

    renderItem = ({ item }) => {
        return (
            <TouchableOpacity
                onPress={() => this.handleSelect(item)}
                style={{
                    backgroundColor: '#fff',
                    height: 40,
                    paddingLeft: 10,
                    justifyContent: 'center'
                }}
            >
                <Text style={{ fontSize: 14, color: '#333' }}>
                    {item.toUpperCase()}
                </Text>
            </TouchableOpacity>
        );
    };

    render() {
        let data = this.props.data;

        return (
            <View style={[ contentStyle, { justifyContent: 'center' } ]}>
                <TouchableOpacity
                    style={{
                        flex: 1,
                        flexDirection: 'row',
                        alignItems: 'center'
                    }}
                    onPress={this.show}
                >
                    <Text
                        numberOfLines={1}
                        style={{ color: this.value ? '#ccc' : '#fff3' }}
                    >
                        {(
                            this.value ||
                            this.props.placeholder ||
                            ''
                        ).toUpperCase()}
                    </Text>
                </TouchableOpacity>

                <Modal
                    transparent
                    animationType='fade'
                    visible={this.visible}
                    onRequestClose={this.hide}
                >
                    <View
                        style={{
                            flex: 1,
                            backgroundColor: '#0005',
                            alignItems: 'center',
                            paddingTop: 80
                        }}
                    >
                        <View
                            style={{
                                width: '80%',
                                backgroundColor: '#fff',
                                borderRadius: 5,
                                maxHeight: '80%',
                                overflow: 'hidden'
                            }}
                        >
                            <FlatList
                                data={data}
                                keyExtractor={i => i}
                                getItemLayout={(_, index) => {
                                    const height = 40 + HairSpacer.width;
                                    return {
                                        length: height,
                                        offset: height * index,
                                        index
                                    };
                                }}
                                ItemSeparatorComponent={HairSpacer}
                                renderItem={this.renderItem}
                            />
                        </View>
                        <TouchableOpacity
                            onPress={this.hide}
                            style={{ marginTop: 12 }}
                        >
                            <Icon
                                name='ios-close-circle'
                                size={50}
                                color='#ccc'
                            />
                        </TouchableOpacity>
                    </View>
                </Modal>
            </View>
        );
    }
}

export default Selector;

const contentStyle = {
    flex: 1,
    backgroundColor: '#0003',
    paddingLeft: 10,
    borderRadius: 3
};

I'm having an issue with scrolling in lists that are in modals ever since upgrading to the latest React-Native version (0.55.4). In this case it is a Flatlist

The Flatlist with the problem is inside a modal, which is in another modal that is rendered as a footer ponent on another Flatlist (it is an add button).

Please help! Thank you

Code:

Flatlist Footer Component (Add Button):

@observer
class AddButton extends Component {
    @observable visible = false;

    constructor(props) {
        super(props);
        this.state = {
            mergeName: '',
            coin: undefined
        };
    }
    show = () => {
        this.visible = true;
    };

    hide = () => {
        this.visible = false;
    };

    render() {

        return (
            <View>
                <Button
                    primary
                    onPress={() => {
                        this.show();
                    }}
                    title={'add'}
                    style={{
                        width: '50%',
                        alignSelf: 'center',
                        marginVertical: 16
                    }}
                />
                <Modal
                    visible={this.visible}
                    animationType='slide'
                    onRequestClose={this.hide}
                >
                    <Screen>
                        <View style={{ padding: 5, backgroundColor: '#0003' }}>
                            <TouchableOpacity
                                style={{
                                    width: '50%',
                                    height: 40,
                                    paddingHorizontal: 10,
                                    justifyContent: 'center'
                                }}
                                onPress={this.hide}
                            >
                                <Text style={{ color: '#fff' }}>
                                    {'cancel'}
                                </Text>
                            </TouchableOpacity>
                        </View>

                        <View>
                            <Row>
                                <RowLabel>{'coin'}:</RowLabel>
                                <Selector
                                    force
                                    ref={'mySelector'}
                                    value={this.coin}
                                    onSelect={coin => {
                                        this.handleSelect();
                                    }}
                                    data={allCoins}
                                />
                            </Row>
                            <Button
                                primary
                                onPress={this.handleSubmit}
                                title={this.props.i18n.'add'}
                                style={{
                                    width: '50%',
                                    alignSelf: 'center',
                                    marginVertical: 16
                                }}
                            />
                        </View>
                    </Screen>
                </Modal>
            </View>
        );
    }
}

export default AddButton;

const contentStyle = {
    flex: 1,
    backgroundColor: '#0003',
    paddingLeft: 10,
    borderRadius: 3
};

const Row = ({ style, ...rest }) => (
    <View
        style={[
            {
                height: 60,
                flexDirection: 'row',
                alignItems: 'center',
                padding: 10,
                marginRight: 10
            },
            style
        ]}
        {...rest}
    />
);

const RowLabel = props => (
    <Text style={{ width: 80, color: '#ccc' }} {...props} />
);

const Input = (props: TextInputProperties) => (
    <View style={contentStyle}>
        <TextInput
            placeholderTextColor='#fff3'
            style={{ color: '#ccc', flex: 1, fontSize: 14 }}
            {...props}
        />
    </View>
);

Problematic Flatlist in Modal Component (Selector):

@observer
class Selector extends Component {
    @observable value = '';
    @observable visible = false;
    constructor(props) {
        super(props);
        if (props.modify) {
            this.selectValue();
        }
    }

    selectValue = () => {
        this.value = this.props.value;
    };

    show = () => {
        if (this.props.force) this.visible = true;
        if (!this.props.coin) return;
        this.visible = true;
    };

    hide = () => {
        this.filterText = '';
        this.visible = false;
    };

    handleSelect = item => {
        this.value = item;
        if (typeof this.props.onSelect === 'function') {
            this.props.onSelect(item);
        }
        this.hide();
    };

    ponentWillReceiveProps(nextProps) {
        if (nextProps.value !== this.value) {
            this.value = nextProps.value || '';
        }
    }

    renderItem = ({ item }) => {
        return (
            <TouchableOpacity
                onPress={() => this.handleSelect(item)}
                style={{
                    backgroundColor: '#fff',
                    height: 40,
                    paddingLeft: 10,
                    justifyContent: 'center'
                }}
            >
                <Text style={{ fontSize: 14, color: '#333' }}>
                    {item.toUpperCase()}
                </Text>
            </TouchableOpacity>
        );
    };

    render() {
        let data = this.props.data;

        return (
            <View style={[ contentStyle, { justifyContent: 'center' } ]}>
                <TouchableOpacity
                    style={{
                        flex: 1,
                        flexDirection: 'row',
                        alignItems: 'center'
                    }}
                    onPress={this.show}
                >
                    <Text
                        numberOfLines={1}
                        style={{ color: this.value ? '#ccc' : '#fff3' }}
                    >
                        {(
                            this.value ||
                            this.props.placeholder ||
                            ''
                        ).toUpperCase()}
                    </Text>
                </TouchableOpacity>

                <Modal
                    transparent
                    animationType='fade'
                    visible={this.visible}
                    onRequestClose={this.hide}
                >
                    <View
                        style={{
                            flex: 1,
                            backgroundColor: '#0005',
                            alignItems: 'center',
                            paddingTop: 80
                        }}
                    >
                        <View
                            style={{
                                width: '80%',
                                backgroundColor: '#fff',
                                borderRadius: 5,
                                maxHeight: '80%',
                                overflow: 'hidden'
                            }}
                        >
                            <FlatList
                                data={data}
                                keyExtractor={i => i}
                                getItemLayout={(_, index) => {
                                    const height = 40 + HairSpacer.width;
                                    return {
                                        length: height,
                                        offset: height * index,
                                        index
                                    };
                                }}
                                ItemSeparatorComponent={HairSpacer}
                                renderItem={this.renderItem}
                            />
                        </View>
                        <TouchableOpacity
                            onPress={this.hide}
                            style={{ marginTop: 12 }}
                        >
                            <Icon
                                name='ios-close-circle'
                                size={50}
                                color='#ccc'
                            />
                        </TouchableOpacity>
                    </View>
                </Modal>
            </View>
        );
    }
}

export default Selector;

const contentStyle = {
    flex: 1,
    backgroundColor: '#0003',
    paddingLeft: 10,
    borderRadius: 3
};
Share Improve this question asked May 25, 2018 at 9:18 ionushionush 3532 gold badges6 silver badges12 bronze badges
Add a ment  | 

7 Answers 7

Reset to default 6

I fixed this issue by Defining a fixed height for the flatlist container.

For E.g

<View style={{height: 300}}>
   {hasResults ? (
       <FlatList
             data={searchResults}
             renderItem={renderItem}
             keyExtractor={(item): string => {
             return item.id;
            }}
             showsVerticalScrollIndicator={false}
         />
    ) : undefined}
</View>

According to official react native docs scrollview should have a bounded height to work. I think same applies to flatlist.

https://reactnative.dev/docs/scrollview

Keep in mind that ScrollViews must have a bounded height in order to work, since they contain unbounded-height children into a bounded container (via a scroll interaction). In order to bound the height of a ScrollView, either set the height of the view directly (discouraged) or make sure all parent views have bounded height. Forgetting to transfer {flex: 1} down the view stack can lead to errors here, which the element inspector makes quick to debug.

The only thing that worked for me was wrapping the inner items inside of the FlatList inside of Pressable

Make sure you have added the Flatlist in ScrollView and add keyboardShouldPersistTaps='always'

<ScrollView style={{ flex: 1 }} keyboardShouldPersistTaps='always'>
            <FlatList
              .................
            />
 </ScrollView>

Just add keyboardShouldPersistTaps='always' to FlatList

Instead of TouchableOpacity use TouchableWithoutFeedback. It worked for me. Sample is below.

<TouchableWithoutFeedback onPress={onClose} activeOpacity={1} style={styles.modalBackground}></TouchableWithoutFeedback>

Add every renderItem ponent inside TouchableOpacity and use activeOpacity={1} to disable opacity change on press

renderItem={({ item }) => 
<TouchableOpacity activeOpacity={1}>
  <Item>
<TouchableOpacity>

I solve with ScrollView, like this:

              <ScrollView>
                <FlatList
                  data={this.state.dataSource}
                  renderItem={({ item, index }) => (
                    <CountryItem item={item} index={index}/>
                  )}
                  horizontal={false}
                  onEndThreshold={0}
                  keyExtractor={item => ''.concat(Math.random())}/>
              </ScrollView>

or use ListView.

本文标签: javascriptReactNative Flatlist in Modal unable to scrollStack Overflow