theapache64
theapache64

Reputation: 11734

FlatList inside ScrollView doesn't scroll

I've 4 FlatLists with maxHeight set to 200 inside a ScrollView.

<ScrollView>
  <FlatList/>
  <FlatList/>
  <FlatList/>
  <FlatList/>
</ScrollView>

and when I try to scroll a FlatList, it doesn't scroll but the ScrollView scrolls. How do I fix this issue ?

Full Source Code

import { Component, default as React } from 'react';
import { FlatList, ScrollView, Text } from 'react-native';

export  class LabScreen extends Component<{}> {
  render() {
    return (
      <ScrollView>
        {this.renderFlatList('red')}
        {this.renderFlatList('green')}
        {this.renderFlatList('purple')}
        {this.renderFlatList('pink')}
      </ScrollView>
    );
  }

  getRandomData = () => {
    return new Array(100).fill('').map((item, index) => {
      return { title: 'Title ' + (index + 1) };
    });
  };

  renderFlatList(color: string) {
    return (
      <FlatList
        data={this.getRandomData()}
        backgroundColor={color}
        maxHeight={200}
        marginBottom={50}
        keyExtractor={(item, index) => index.toString()}
        renderItem={({ item }) => <Text>{item.title}</Text>}
      />
    );
  }
}

snack.expo link

Upvotes: 61

Views: 154737

Answers (11)

Soban Arshad
Soban Arshad

Reputation: 1411

Caution

There are some reported cases in which ScrollView imported from 'react-native' is now working properly. For instance this nested scroll issue, I even tried

nestedScrollEnabled

Still it didn't work

On the other hand importing ScrollView from

import { ScrollView } from 'react-native-gesture-handler';

is working fine even without nestedScollEnabled.

Thanks.

Upvotes: 0

Jonathan Coletti
Jonathan Coletti

Reputation: 528

Make sure you add nestedScrollEnabled to each flatlist / scrollview but most importantly make sure you do not use pos absolute and allow your screen to flex to be able to scroll

Upvotes: 0

JoshJoe
JoshJoe

Reputation: 1630

I'm surprised that none of the answers actually worked for me. I went searching for the reason ScrollView and FlatList don't work together and found that there are props on FlatList that can accomodate the header and footer areas above and below my FlatList. If I use this I can make sure the whole screen still scrolls and I don't get the error.

Here is where I found this answer and I've put an example below.

<View>
  <FlatList
    ListHeaderComponent={<View><Text>Top of screen content goes here</Text></View>}
    keyExtractor={(item) => item._id}
    data={[{_id: 1, text: 'one'}, {_id: 2, text: 'two'}]
    renderItem={({item}) => (<View><Text>{item.text}</Text></View>)}
  />
</View>

Upvotes: 6

Bruno Luiz
Bruno Luiz

Reputation: 74

The better answer is to put a horizontal ScrollView inside of the other ScrollView and then the FlatList

Upvotes: -1

i-wizard
i-wizard

Reputation: 314

This is the simplest answer that requires zero configuration.. and it works like a charm

<ScrollView horizontal={false}>
    <ScrollView horizontal={true}>
        <Flatlist
          ....
          ....
        />
    </ScrollView>
</ScrollView>

Upvotes: 22

Eric Le Fort
Eric Le Fort

Reputation: 2691

I was having a very similar issue until I came across an almost complete solution in a very helpful comment on one of the GitHub issues for the react-native project: https://github.com/facebook/react-native/issues/1966#issuecomment-285130701.

The issue is that the parent component is the only one registering the scroll event. The solution is to contextually decide which component should actually be handling that event based on the location of the press.

You'll need to slightly modify your structure to:

<View>
  <ScrollView>
    <View>
      <FlatList />
    </View>
    <View>
      <FlatList />
    </View>
    <View>
      <FlatList />
    </View>
    <View>
      <FlatList />
    </View>
  </ScrollView>
</View>;

The only thing I had to change from the GitHub comment was to use this._myScroll.contentOffset instead of this.refs.myList.scrollProperties.offset.

I've modified your fully working example in a way that allows scrolling of the inner FlatLists.

import { Component, default as React } from "react";
import { View, FlatList, ScrollView, Text } from "react-native";

export default class LabScreen extends Component<{}> {
  constructor(props) {
    super(props);
    this.state = { enableScrollViewScroll: true };
  }

  render() {
    return (
      <View
        onStartShouldSetResponderCapture={() => {
          this.setState({ enableScrollViewScroll: true });
        }}
      >
        <ScrollView
          scrollEnabled={this.state.enableScrollViewScroll}
          ref={(myScroll) => (this._myScroll = myScroll)}
        >
          {this.renderFlatList("red")}
          {this.renderFlatList("green")}
          {this.renderFlatList("purple")}
          {this.renderFlatList("pink")}
        </ScrollView>
      </View>
    );
  }

  getRandomData = () => {
    return new Array(100).fill("").map((item, index) => {
      return { title: "Title " + (index + 1) };
    });
  };

  renderFlatList(color: string) {
    return (
      <View
        onStartShouldSetResponderCapture={() => {
          this.setState({ enableScrollViewScroll: false });
          if (
            this._myScroll.contentOffset === 0 &&
            this.state.enableScrollViewScroll === false
          ) {
            this.setState({ enableScrollViewScroll: true });
          }
        }}
      >
        <FlatList
          data={this.getRandomData()}
          backgroundColor={color}
          maxHeight={200}
          marginBottom={50}
          keyExtractor={(item, index) => index.toString()}
          renderItem={({ item }) => <Text>{item.title}</Text>}
        />
      </View>
    );
  }
}

Hopefully you find this useful!

Upvotes: 40

Helmons
Helmons

Reputation: 19

Use map instead of Flatlist, same result and don't break the application

Minha conta
   {
      buttonsProfile.map(button => (
         <ArrowButton 
              key={button.key}
              title={button.title}
              iconName={button.icon} 
              toogle={button.toogle}
              onPress={() => {navigation.navigate(button.route)}}
          />
      ))
    }
                 

Upvotes: -1

Sunday David
Sunday David

Reputation: 115

Using View with a flex:1 instead of ScrollView worked for me.

Upvotes: 1

Vojd Naroda
Vojd Naroda

Reputation: 191

I fixed my problem with nested FlatList not being able to scroll items on android by simply importing FlatList

import { FlatList } from 'react-native-gesture-handler';

If this would not work, also try to import ScrollView.

import { ScrollView } from 'react-native';
// OR
import { ScrollView } from 'react-native-gesture-handler';

You need to play around with these imports, at least it worked in my case.

Upvotes: 19

rnk
rnk

Reputation: 2539

We can use the built-in nestedscrollenabled prop for the children FlatList/ScrollView components.

<FlatList nestedScrollEnabled />

This is only required for Android (Nested scrolling is supported by default on iOS).

Upvotes: 135

Roberto Clavijo
Roberto Clavijo

Reputation: 149

Try to set the FlatList as nested

nestedScrollEnabled={true}

Upvotes: 10

Related Questions