nuclearpasta / react-native-drax

A drag-and-drop system for React Native
MIT License
554 stars 69 forks source link

DraxScrollView nested inside a DraxScrollView causes DraxView receiving area to be misplaced #137

Open timknapp-qs opened 2 years ago

timknapp-qs commented 2 years ago

Hi @lafiosca. First of all, I would like to say that I love the library. Great work! I have run into a very specific issue. I need to be able to scroll vertically and also scroll horizontally. And I would like to have autoscrolling so I use your DraxScrollView as opposed to ScrollView. However, the nested DraxScrollView with the horizontal={true} prop causes some unwanted behavior. The behavior is this: A receiving DraxView does not receive properly if the screen has been scrolled down vertically. The receiving area is pushed down (no longer inside the DraxView) in proportion to how far the screen has been scrolled. See attachments. This happens on both iOS and Android. In this code, the receivingStyle changes the background color to blue when an item enters the DraxView. The top DraxView words fine, but the one at the bottom that you have to scroll down to does not. If I change the nested DraxScrollView to a ScrollView then the drop area works as expected but then I lose the autoscroll. I hope this all makes sense! Let me know if it is not clear. Thanks!

import { View, Text, ScrollView } from 'react-native';
import { DraxProvider, DraxScrollView, DraxView } from 'react-native-drax';

const items = ['one', 'two', 'three', 'four'];

const DragNDropTest = () => {
  return (
    <View style={{ backgroundColor: 'white' }}>
      <DraxProvider>
        <View />
        <DraxScrollView
          contentContainerStyle={{
            paddingBottom: 200,
          }}
          style={{
            minHeight: '100%',
          }}
        >
          {/* If this second DraxScrollView is switched to ScrollView then the drop works but then horizontal autoscroll doesn't work */}
          <DraxScrollView
            contentContainerStyle={{
              minWidth: '100%',
              minHeight: '100%',
              justifyContent: 'center',
              alignItems: 'center',
              flexDirection: 'column',
            }}
            style={{
              minHeight: '100%',
            }}
            horizontal
          >
            <DraxView
              style={{
                height: 100,
                width: 100,
                borderWidth: 2,
              }}
              receivingStyle={{ backgroundColor: 'blue' }}
              onReceiveDragEnter={() =>
                console.log('has entered top drop zone')
              }
            />
            <DraxView
              style={{
                height: 500,
                width: 500,
                borderWidth: 2,
                margin: 10,
              }}
              onStartShouldSetResponder={() => true}
            >
              {items.map((item, index) => (
                <DraxView
                  key={index}
                  style={{
                    height: 90,
                    width: 90,
                    backgroundColor: 'red',
                    marginTop: 10,
                  }}
                  onDragStart={() => console.log('has started')}
                >
                  <Text>{item}</Text>
                </DraxView>
              ))}
            </DraxView>
            {/* This last DraxView is the one that does not behave as expected, if the screen has been scrolled vertically */}
            <DraxView
              style={{
                height: 100,
                width: 100,
                borderWidth: 2,
              }}
              receivingStyle={{ backgroundColor: 'blue' }}
              onReceiveDragEnter={() =>
                console.log('has entered bottom drop zone')
              }
            />
            <View />
          </DraxScrollView>
        </DraxScrollView>
      </DraxProvider>
    </View>
  );
};

export default DragNDropTest;

IMG_2489

https://user-images.githubusercontent.com/78120827/165841777-437ac87c-897a-480a-bc81-a1016c8c8837.MP4

lafiosca commented 2 years ago

Thanks for the kind words, @timknapp-qs. And thanks for the very clear reproduction of the issue you're experiencing. My first thought upon seeing this is that DraxScrollView needs to honor the scroll position of its parent DraxScrollView, the same way that regular DraxViews do. Given that DraxScrollView is implemented via another DraxView itself, I'm a little surprised that it is not already doing so, but I am sure there is a reason for it. Unfortunately I do not and likely will not have time to dive into this soon. I am disappointed by the current state of the library, but I have not been able to afford the energy to put any serious work into it for a while now. I am open to reviewing and accepting PRs if other folks have the bandwidth to fix this.

I have labeled this issue as a bug, but I have also labeled it as an enhancement because it occurs to me that an X/Y-scrolling DraxScrollView could also be useful.

timknapp-qs commented 2 years ago

Thanks @lafiosca for the response! At some point I might be able to dive into the code if my boss allows it haha. Good luck with everything!