How-to make React Native lists bounce only from the bottom?

kytwb picture kytwb · Aug 2, 2017 · Viewed 8.5k times · Source

I'm using a FlatList with a consequent ListHeaderComponent as the root component of my screen. I don't want the top of it to bounce on scroll, but I want to keep the bottom bouncing for UX'n'feel purpose as the FlatList supports infinite scroll. Any ideas how-to?

Answer

bend picture bend · Oct 2, 2017

A solution would be to listen to scroll events and check whether the bounces prop inherited from ScrollView should be enabled or not. Note that I personally find this solution to be a bit of an overkill, but it works as expected.

You can find a fully working example at the following URL: https://snack.expo.io/SkL-L0knZ. You can preview it right in the browser and you can also try it on your mobile device with the Expo app.

Here is the result (forget about the lag, as this was captured in the browser):

react native scrollview bounces

And here is the relevant source code:

export default class App extends Component {

    constructor (props) {
        super(props);
        this.state = { bounces: false };
        this.renderHeader = this.renderHeader.bind(this);
        this._onScroll = this._onScroll.bind(this);
    }

    _onScroll (event) {
        const scrollPosition = event && event.nativeEvent && event.nativeEvent.contentOffset && event.nativeEvent.contentOffset.y;
        let newBouncesValue;

        if (scrollPosition < viewportHeight / 3) {
            newBouncesValue = false;
        } else {
            newBouncesValue = true;
        }

        if (newBouncesValue === this.state.bounces) {
            return;
        }

        this.setState({ bounces: newBouncesValue });
    }

    renderHeader () {
        const { bounces } = this.state;
        const style = [
            styles.header,
            { backgroundColor : bounces ? 'darkseagreen' : 'firebrick'}
        ];

        return (
            <Text style={style}>{ bounces ? 'CAN BOUNCE' : "WON'T BOUNCE"}</Text>
        );
    }

    renderItem ({item}) {
        return (
            <Text style={styles.row}>{item.key}</Text>
        );
    }

    render() {
        return (
            <View style={styles.container}>
                { this.renderHeader() }
                <FlatList
                    data={DUMMY_DATA}
                    renderItem={this.renderItem}
                    onScroll={this._onScroll}
                    bounces={this.state.bounces}
                    scrollEventThrottle={16}
                />
            </View>
        );
    }
}