react-native-draggable-flatlist not working inside ScrollView

8.1k Views Asked by At

I am struggling for last couple of months to achieve a requirement where I'm having a draggable flatlist and a flatlist in a single scrollview and I should able to scroll the whole content.

The draggable flatlist should have autoscroll as well, that means when the list is too long and I'm trying to drag it out of the viewport, the list should scroll automatically unless I drop it.

I know the requirement is pretty much tricky but I am not getting any clue to make it work completely.

I am using the below code and I am using 'react-native-draggable-flatlist'(https://github.com/computerjazz/react-native-draggable-flatlist) for this purpose.

Code:

import React from 'react';
import {
  SafeAreaView,
  StyleSheet,
  ScrollView,
  View,
  Text,
  StatusBar,
  TouchableOpacity
} from 'react-native';

import {
  Header,
  LearnMoreLinks,
  Colors,
  DebugInstructions,
  ReloadInstructions,
} from 'react-native/Libraries/NewAppScreen';
import DraggableFlatList from 'react-native-draggable-flatlist'
import { Component } from 'react'

const exampleData = [...Array(20)].map((d, index) => ({
  key: `item-${index}`, // For example only -- don't use index as your key!
  label: index,
  backgroundColor: `rgb(${Math.floor(Math.random() * 255)}, ${index *
  5}, ${132})`
}));

class App extends Component {
  state = {
    data: exampleData,
    scrollEnabled: true
  };
  onEnableScroll = (value: boolean) => {
    this.setState({
      enableScrollViewScroll: value,
    });
  };

  renderItem = ({ item, index, drag, isActive }) => {
    return (
      <TouchableOpacity
        style={{
          height: 100,
          backgroundColor: isActive ? "blue" : item.backgroundColor,
          alignItems: "center",
          justifyContent: "center"
        }}
        onLongPress={drag}
      >
        <Text
          style={{
            fontWeight: "bold",
            color: "white",
            fontSize: 32
          }}
        >
          {item.label}
        </Text>
      </TouchableOpacity>
    );
  };

  render() {
    return (
      <ScrollView
        style={{ backgroundColor: '#000', flex: 1 }}
        contentContainerStyle={{ paddingTop: 800, paddingBottom: 100 }}
        scrollEnabled={this.state.scrollEnabled}
      >
        <DraggableFlatList
          data={this.state.data}
          renderItem={this.renderItem}
          keyExtractor={(item, index) => `draggable-item-${item.key}`}
          onMoveBegin={() => this.setState({ scrollEnabled: false })}
          onMoveEnd={({ data }) => {
            this.setState({ scrollEnabled: true, data });
          }}
        />

        <FlatList
          data={this.state.data}
          renderItem={this.renderItem}
          keyExtractor={(item, index) => `draggable-item-${item.key}`}
        />

      </ScrollView>
    );
  }
}

const styles = StyleSheet.create({
  scrollView: {
    backgroundColor: Colors.lighter,
  },
  engine: {
    position: 'absolute',
    right: 0,
  },
  body: {
    backgroundColor: Colors.white,
  },
  sectionContainer: {
    marginTop: 32,
    paddingHorizontal: 24,
  },
  sectionTitle: {
    fontSize: 24,
    fontWeight: '600',
    color: Colors.black,
  },
  sectionDescription: {
    marginTop: 8,
    fontSize: 18,
    fontWeight: '400',
    color: Colors.dark,
  },
  highlight: {
    fontWeight: '700',
  },
  footer: {
    color: Colors.dark,
    fontSize: 12,
    fontWeight: '600',
    padding: 4,
    paddingRight: 12,
    textAlign: 'right',
  },
});

export default App;
2

There are 2 best solutions below

1
On

You should use ListFooterComponent and ListHeaderComponent method to render items.

Please change your render method like below code.

render() {
      return (
        <View
          style={{ backgroundColor: '#000', flex: 1 }}
        >
          <DraggableFlatList
            data={this.state.data}
            renderItem={this.renderItem}
            keyExtractor={(item, index) => `draggable-item-${item.key}`}
            onMoveBegin={() => this.setState({ scrollEnabled: false })}
            onMoveEnd={({ data }) => {
              this.setState({ scrollEnabled: true, data });
            }}
            ListFooterComponent={() => {
              return <View>
                <FlatList
                  data={this.state.data}
                  renderItem={this.renderItem}
                  keyExtractor={(item, index) => `draggable-item-${item.key}`}
                />
              </View>
            }}
          />
        </View>
      );
}
0
On

In my case, I have another ScrollView composition. My solution was found in this repository:

React Native Draggable FlatList

I replaced:

  1. ScrollView -> NestableScrollContainer
  2. DraggableFlatList -> NestableDraggableFlatList

Initially there was one DraggableFlatList but in this case I was able to scroll via the DraggableFlatList