question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Draggable Flatlist inside a ScrollView doesn't account for scrolled offset

See original GitHub issue

When nesting a DraggableFlatlist inside a ScrollView the proxy components rendered while dragging are not positioned relative to the scrolled position of the parent container (the ScrollView).

This means they either disappear or render offset from the mouse/touch position by the scrolled amount.

In the below test case, I’m offsetting the position of the draggable flatlist using content container padding on the ScrollView. Dragging/re-ordering still works by disabling the scrollview with onMoveBegin

I would guess that you need to position the proxy component absolutely to the touch position within the screen, not just the view.

import React, { PureComponent } from 'react';
import { ScrollView, Text, TouchableOpacity } from 'react-native';
import DraggableFlatList from 'react-native-draggable-flatlist';

export default class Test extends PureComponent {
  state = {
    scrollEnabled: true,
    data: [
      { label: '1', key: '1' },
      { label: '2', key: '2' },
      { label: '3', key: '3' },
      { label: '4', key: '4' },
    ],
  };

  renderItem = ({
    item, isActive, index, move, moveEnd,
  }) => (
    <TouchableOpacity
      activeOpacity={0.9}
      style={{
        flex: 1,
        alignItems: 'center',
        height: 60,
        borderColor: isActive ? 'white' : 'black',
        borderWidth: 2,
      }}
      onLongPress={move}
      onPressOut={moveEnd}
    >
      <Text style={{ fontSize: 30, color: 'white' }}>
        {item.label}
      </Text>
    </TouchableOpacity>
  );

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

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:19
  • Comments:26 (3 by maintainers)

github_iconTop GitHub Comments

16reactions
spacewafflecommented, May 31, 2019

I have a proposed fix that works for me. It adds an optional prop called scrollingContainerOffset that allows us to inject the offset of the surrounding scrollview container. Starting on onStartShouldSetPanResponderCapture line 88:

if (this.props.scrollingContainerOffset !== undefined) {
    this._offset.setValue((this._additionalOffset + this._containerOffset - this.props.scrollingContainerOffset - this._androidStatusBarOffset) * -1)
} else {
    this._offset.setValue((this._additionalOffset + this._containerOffset - this._androidStatusBarOffset) * -1)
}

To calculate it properly you’d need to setup a scrollview with the following setup in the app itself so that your app will pass the prop to Draggable Flatlist.

state = {
    ...
    scrollOffset: 0,
    ...
};

render() {
    return (
        <ScrollView
            onScrollEndDrag={({ nativeEvent }) => { this.setState({ scrollOffset: nativeEvent.contentOffset['y'] }); }}
            onMomentumScrollEnd={({ nativeEvent }) => { this.setState({scrollOffset: nativeEvent.contentOffset['y']}); }}
        >
            <DraggableFlatList
                ...
                scrollingContainerOffset={this.state.scrollOffset}
                ...
            />
       </ScrollView>
    );
}
3reactions
SantiSarGoncommented, Apr 21, 2020

Hello, has the solution been implemented?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Draggable Flatlist inside a ScrollView doesn't account for scrolled ...
When nesting a DraggableFlatlist inside a ScrollView the proxy components rendered while dragging are not positioned relative to the scrolled position of ...
Read more >
FlatList inside ScrollView doesn't scroll - Stack Overflow
The issue is that the parent component is the only one registering the scroll event. The solution is to contextually decide which component ......
Read more >
React Native FlatList Scroll to Offset - YouTube
Learn how to scroll to an offset for a FlatList in React Native.
Read more >
react-native-draggable-flatlist - npm
Start using react-native-draggable-flatlist in your project by running `npm i ... (offset: number) => void, Called with scroll offset.
Read more >
useAnimatedScrollHandler | React Native Reanimated
This object will persist in between scroll event occurrences and you can read and write any data to ... ScrollView component to which...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found