Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FlatList scrolling broken when absolute positioned

React Native: 0.63.3

First let me start by saying I have now spent ~6 hrs trying to solve this and I have yet to find a solution online anywhere that works for my setup.

What I have is a page with the following layout(greatly simplified from actual use case, but same issue)

Each of the red boxes is a View. The search Input drop down is set to overlay over the red box views, which it does

enter image description here

enter image description here

The problem though is that the FlatList will only scroll if my mouse is in that space between the search input and the first View. Once my mouse is overtop of the View the FlatList seems to ignore the scrolling.

Here is the most basic version of that code:

import React, { useState } from 'react';
import { FlatList, View, TextInput, TouchableOpacity, Text, StyleSheet } from 'react-native';

export const myStyles = StyleSheet.create({
    container: {
        minWidth: '100%',
        borderRadius: 3,
        padding: 10,
        backgroundColor: 'white'
    },
    search: {
        display: 'flex',
        flexDirection: 'column',
        justifyContent: 'space-between',
        flex: 1,
        height: 50,
        marginBottom: 50
    },
    textInput: {
        width: '100%',
        borderWidth: 1,
        borderColor: 'blue'
    },
    flatlistContainer: {
        position: 'absolute',
        zIndex: 99999,
        height: 180,
        width: 300
    },
    inputRow: {
        display: 'flex',
        flexDirection: 'row',
        justifyContent: 'space-between',
        paddingLeft: 0,
        paddingRight: 0,
        paddingTop: 5,
        paddingBottom: 5
    },
    itemRow: {
        flexDirection: 'row',
        justifyContent: 'space-between',
        backgroundColor: 'silver'
    },
    buttonText: {
        alignSelf: 'flex-start',
        fontSize: 13,
        margin: 0,
        padding: 5
    }
});

const MyComponent = () => {
    const [inputValue, setInputValue] = useState('');

    const options = [
        {label: 'one', value: 'one'},
        {label: 'two', value: 'two'},
        {label: 'three', value: 'three'},
        {label: 'four', value: 'four'},
        {label: 'five', value: 'five'},
        {label: 'six', value: 'six'},
        {label: 'seven', value: 'seven'},
        {label: 'eight', value: 'eight'},
        {label: 'nine', value: 'nine'},
        {label: 'ten', value: 'ten'},
        {label: 'eleven', value: 'two'}
    ];

    return (
        <View style={myStyles.container}>
            <View style={[myStyles.inputRow, { zIndex: 9999999 }]}>
                <View style={[myStyles.search]}>
                    <TextInput
                        value={inputValue}
                        onChangeText={(value) => setInputValue(value)}
                        placeholder="Search..."
                        style={myStyles.textInput}
                    />
                    <View>
                        <View style={myStyles.flatlistContainer}>
                            <FlatList
                                data={options}
                                renderItem={({ item }) => (
                                    <TouchableOpacity onPress={() => console.log ('pressed')}>
                                        <View style={myStyles.itemRow}>
                                            <Text style={myStyles.buttonText}>
                                                {item.label}
                                            </Text>
                                        </View>
                                    </TouchableOpacity>
                                )}
                                keyExtractor={item => item.label}
                            />
                        </View>
                    </View>
                </View>
            </View>

            <View style={[myStyles.inputRow, { borderWidth: 1, borderColor: 'red', height: 50 }]} />
            <View style={[myStyles.inputRow, { borderWidth: 1, borderColor: 'red', height: 50 }]} />
            <View style={[myStyles.inputRow, { borderWidth: 1, borderColor: 'red', height: 50 }]} />
            <View style={[myStyles.inputRow, { borderWidth: 1, borderColor: 'red', height: 50 }]} />
            <View style={[myStyles.inputRow, { borderWidth: 1, borderColor: 'red', height: 50 }]} />
            <View style={[myStyles.inputRow, { borderWidth: 1, borderColor: 'red', height: 50 }]} />
        </View>
    );
}


export default MyComponent;
like image 792
P-Rick Stephens Avatar asked May 03 '26 10:05

P-Rick Stephens


1 Answers

Finally figured out my problem. Had to do with how Views were nested. Despite the flatlist rendering on top of the other items the scroll didn't work. This new layout also gets the scrolling of the Flatlist working again

export const myStyles = StyleSheet.create({
    inputRow: {
        display: 'flex',
        flexDirection: 'row',
        justifyContent: 'space-between',
        paddingLeft: 0,
        paddingRight: 0,
        paddingTop: 5,
        paddingBottom: 5
    },
    itemRow: {
        flexDirection: 'row',
        justifyContent: 'space-between',
        backgroundColor: 'silver'
    },
    buttonText: {
        alignSelf: 'flex-start',
        fontSize: 13,
        margin: 0,
        padding: 5
    }
});

const MyComponent = () => {
    const [inputValue, setInputValue] = useState('');

    const options = [
        {label: 'one', value: 'one'},
        {label: 'two', value: 'two'},
        {label: 'three', value: 'three'},
        {label: 'four', value: 'four'},
        {label: 'five', value: 'five'},
        {label: 'six', value: 'six'},
        {label: 'seven', value: 'seven'},
        {label: 'eight', value: 'eight'},
        {label: 'nine', value: 'nine'},
        {label: 'ten', value: 'ten'},
        {label: 'eleven', value: 'two'}
    ];

    return (
        <View style={{
            borderWidth: 1,
            borderColor: 'blue'
        }}>
            <View style={{
                borderWidth: 2,
                borderColor: 'orange',
                position: 'absolute',
                left: 0,
                right: 0,
                top: 0,
                bottom: 0,
                zIndex: 99
            }}>
                <TextInput
                    value={inputValue}
                    onChangeText={(value) => setInputValue(value)}
                    placeholder="Search..."
                    style={{ backgroundColor: 'grey' }}
                />
                <FlatList
                    data={options}
                    renderItem={({ item }) => (
                        <TouchableOpacity onPress={() => console.log ('pressed')}>
                            <View style={myStyles.itemRow}>
                                <Text style={myStyles.buttonText}>
                                    {item.label}
                                </Text>
                            </View>
                        </TouchableOpacity>
                    )}
                    keyExtractor={(item) => item.label}
                />
            </View>
            <View>
                <View style={[myStyles.inputRow, { borderWidth: 1, borderColor: 'red', height: 50 }]} />
                <View style={[myStyles.inputRow, { borderWidth: 1, borderColor: 'red', height: 50 }]} />
                <View style={[myStyles.inputRow, { borderWidth: 1, borderColor: 'red', height: 50 }]} />
                <View style={[myStyles.inputRow, { borderWidth: 1, borderColor: 'red', height: 50 }]} />
                <View style={[myStyles.inputRow, { borderWidth: 1, borderColor: 'red', height: 50 }]} />
                <View style={[myStyles.inputRow, { borderWidth: 1, borderColor: 'red', height: 50 }]} />
            </View>
        </View>
    );
}

export default MyComponent;
like image 110
P-Rick Stephens Avatar answered May 06 '26 00:05

P-Rick Stephens