nuclearpasta / react-native-drax

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

Item position error when dragging if inside a list #77

Open rahulreghunath opened 3 years ago

rahulreghunath commented 3 years ago

When dragging an item the item appears below than it actually should be. It only shows this error in a list of DragViews and the list has more items that cover the viewport( items initially hidden in scroll). No problem when dragging topmost items in the list.

import React, { useState } from 'react';
import {
  Text,
  View,
  StyleSheet,
} from 'react-native';

import { DraxProvider, DraxView} from 'react-native-drax';
import { FlatList } from 'react-native-gesture-handler';

const App = () => {
  const [moving, setMoving] = useState(false);
  const [lists, setLists] = useState(['red', 'green', 'blue', 'yellow']);
  const [received, setReceived] = useState([]);
  const [staged, setStaged] = useState([]);
  return (
    <DraxProvider>
      <View style={styles.container}>
        <DraxView
          style={[styles.centeredContent, styles.receivingZone, styles.magenta]}
          receivingStyle={styles.receiving}
          renderContent={({ viewState }) => {
            const receivingDrag = viewState && viewState.receivingDrag;
            const payload = receivingDrag && receivingDrag.payload;
            return (
              <>
                <Text>Receiving Zone</Text>
                <Text style={styles.incomingPayload}>{payload || '-'}</Text>
                <Text style={styles.received}>{received.join(' ')}</Text>
              </>
            );
          }}
        />
        <View style={styles.palette}>
          <FlatList
          style={{height:100,width:'100%'}}
            data={lists}
            renderItem={({ item }) => (
              <DraxView
                onDragStart={() => {
                  setMoving(true);
                }}
                onDragEnd={() => {
                  setMoving(false);
                }}
                onDragDrop={() => {
                  setMoving(false);
                }}
                animateSnapback
                receptive
                style={[styles.centeredContent, styles.draggableBox, { backgroundColor: item }]}
                draggingStyle={styles.dragging}
                dragReleasedStyle={styles.dragging}
                hoverDraggingStyle={styles.hoverDragging}
                dragPayload={item}
                longPressDelay={0}
              >
                <Text>{item}</Text>
              </DraxView>
            )}
          />

        </View>
        <DraxView
          dragPayload={staged.join(' ')}
          draggable={staged.length > 0}
          renderContent={({ viewState }) => {
            const receivingDrag = viewState && viewState.receivingDrag;
            const payload = receivingDrag && receivingDrag.payload;
            const dragging = viewState && viewState.dragStatus !== 0;
            const combinedStyles = [
              styles.centeredContent,
              styles.receivingZone,
              styles.cyan,
            ];
            if (dragging) {
              combinedStyles.push({ opacity: 0.2 });
            } else if (receivingDrag) {
              combinedStyles.push(styles.receiving);
            }
            return (
              <View style={combinedStyles}>
                <Text>Staging Zone</Text>
                <Text style={styles.incomingPayload}>{payload || '-'}</Text>
                <Text style={styles.received}>{staged.join(' ')}</Text>
              </View>
            );
          }}
          renderHoverContent={({ viewState }) => {
            const offsetStyle = viewState.grabOffset
              ? {
                marginLeft: viewState.grabOffset.x - 30,
                marginTop: viewState.grabOffset.y - 30,
              }
              : undefined;
            const combinedStyles = [
              styles.centeredContent,
              styles.draggableBox,
              styles.cyan,
              offsetStyle,
            ];
            if (viewState.dragStatus === 1) {
              combinedStyles.push(styles.hoverDragging);
            }
            return (
              <View style={combinedStyles}>
                <Text style={styles.stagedCount}>{staged.length}</Text>
              </View>
            );
          }}
          onReceiveDragDrop={(event) => {
            setStaged([
              ...staged,
              event.dragged.payload || '?',
            ]);
          }}
          onDragDrop={() => setStaged([])}
        />
      </View>
    </DraxProvider>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 12,
    paddingTop: 40,
    justifyContent: 'space-evenly',
  },
  centeredContent: {
    justifyContent: 'center',
    alignItems: 'center',
  },
  receivingZone: {
    height: 200,
    borderRadius: 10,
  },
  receiving: {
    borderColor: 'red',
    borderWidth: 2,
  },
  incomingPayload: {
    marginTop: 10,
    fontSize: 24,
  },
  received: {
    marginTop: 10,
    fontSize: 18,
  },
  palette: {
    flexDirection: 'row',
    justifyContent: 'space-evenly',
  },
  draggableBox: {
    width: 60,
    height: 60,
    borderRadius: 10,
  },
  green: {
    backgroundColor: '#aaffaa',
  },
  blue: {
    backgroundColor: '#aaaaff',
  },
  red: {
    backgroundColor: '#ffaaaa',
  },
  yellow: {
    backgroundColor: '#ffffaa',
  },
  cyan: {
    backgroundColor: '#aaffff',
  },
  magenta: {
    backgroundColor: '#ffaaff',
  },
  dragging: {
    opacity: 0.2,
  },
  hoverDragging: {
    borderColor: 'magenta',
    borderWidth: 2,
  },
  stagedCount: {
    fontSize: 18,
  },
});

export default App;

https://user-images.githubusercontent.com/28650610/107931887-e7d7d980-6fa2-11eb-8a02-1474bf9ab210.mp4

lafiosca commented 3 years ago

Hello there. I'll start this reply with my standard apology for the state of maintenance of this library right now. Personal circumstances have not afforded me the time to do any deep work on Drax for a while, and I am not fresh on the code. I have a Drax logic documentation project in progress but presently on hold. The goal with that is to make it easier for myself and others to maintain the library without accidentally breaking or changing functionality. I do however keep an eye on the issues and try to answer things off the top of my head if I am able.

The drag hover rendering position will be wrong like this if DraxViews are inside any kind of scrolling container unless that container is also registered with the Drax system to track its scroll position and report it to the registry. This is why DraxScrollView exists, although it is not as fully featured as a FlatList. The documentation and this part of the library could use some additional work, so I will leave this issue open as a reminder. To me it would be ideal if DraxList could be enhanced to provide for this use case, but I will not know for certain whether a separate component is necessary (perhaps DraxFlatList?) until I have an opportunity to mess with the code again.

rahulreghunath commented 3 years ago

Enhancing DraxList would be a better option so that we can order the list and move the item to another list with almost the same logic.

rahulreghunath commented 3 years ago

Anyway DraxScrollView works well in my use case :+1:

lafiosca commented 3 years ago

I'm glad to hear that! If you don't mind, as I mentioned above I'm going to keep this issue open as a reminder that the documentation should be updated to better explain this behavior.

rahulreghunath commented 3 years ago

I'm glad to hear that! If you don't mind, as I mentioned above I'm going to keep this issue open as a reminder that the documentation should be updated to better explain this behavior.

as you wish :smile:

tipaniclayr30 commented 1 year ago

Hello sir, do we already have an updates for this issue?

lafiosca commented 1 year ago

@tipaniclayr30 Hi, per the comments above it seemed this functionality was achievable with the library, but we left this issue open as a reminder to improve the documentation

AbbasTheReckoner commented 6 months ago

Hello, any update on this issue ????