computerjazz / react-native-draggable-flatlist

A drag-and-drop-enabled FlatList for React Native
MIT License
1.95k stars 407 forks source link

iOS: Item floating away on long press, preventing drag and drop to work correctly #304

Open TommasoTate opened 3 years ago

TommasoTate commented 3 years ago

Describe the bug When pressing on an item to start dragging, the item moves away from the touchpoint and drag doesn't work. The issue is iOS only and appears randomly when I'm in debug, whereas is always present in my production build. https://user-images.githubusercontent.com/65722261/127123769-296c613f-f6d8-48d2-9c7d-23ca9c310218.MP4

To Reproduce Here is my implementation code:

const ItemSeparatorComponent = () => <Spacer size={Theme.Sizes.spacing.lg}/>
const FooterComponent = (<Spacer size={SHARE_CTA_SPACER}/>)
const keyExtractor = ([key]) => key

const ItemPlaceholder = () => (
 <Row >
    <Column flex={0}>
      <Placeholder
        borderRadius={10}
        height={10}
        width={10}
      />
    </Column>
    <Column>
      <Placeholder
        height={22}
        width={100}
      />
      <Spacer size={2}/>
      <Placeholder
        height={16}
        width={210}
      />
    </Column>
    <Column flex={0}>
      <Placeholder
        borderRadius={13}
        height={26}
        width={42}
      />
    </Column>
  </Row>)

const ListEmptyComponent = (<View style={{ marginHorizontal: Theme.Sizes.margin.md } }>
  <ItemPlaceholder/>
  <Spacer size={Theme.Sizes.spacing.lg}/>
  <ItemPlaceholder/>
  <Spacer size={Theme.Sizes.spacing.lg}/>
  <ItemPlaceholder/>
  <Spacer size={Theme.Sizes.spacing.lg}/>
  <ItemPlaceholder/>
  <Spacer size={Theme.Sizes.spacing.lg}/>
  <ItemPlaceholder/>
</View>)

  const ListHeaderComponent = useMemo(() => {
    const editCode = () => {}
    const showLandingPage = () => {}
    return (
      <View style={styles.horizontalMargin}>
        <Spacer size={Theme.Sizes.spacing.sm}/>
        <Header
          style={styles.header}
          title={Localization.translate('text_edit')}
          subtitle={Localization.translate('screen_referral__update_landing_page--subtitle')}
        />
        <Column noGutter>
          <Row alignBottom noGutter left>
            <TicketIcon
              color={Theme.Palette.violetBlue500}
              size={Theme.Sizes.iconSize.xxs}
            />
            <ThemedText style={styles.terms}>
              <Link style={styles.link} onPress={showLandingPage}>
                {Localization.translate('landing_page_tutorial_create-cta--show')}
              </Link>
            </ThemedText>
          </Row>
          <Spacer size={Theme.Sizes.spacing.xl}/>
          <Row>
            { !loading && code && <InputShowcase
              mainText={code}
              label={Localization.translate('screen_referral__code_page_label_code')}
              icon={Icon.Names.create}
              iconColor={Theme.Palette.eerieBlack800}
              onPressIcon={editCode}
            />}
            {loading && <InputShowcase.Placeholder />}

          </Row>
          <Spacer size={Theme.Sizes.spacing.xl}/>
          <SectionList.Header containerStyle={styles.sectionHeader} text={Localization.translate('screen_referral__update_landing_page__list__title')}/>
          <Spacer size={Theme.Sizes.spacing.md}/>
        </Column>
      </View>)
  }, [loading, code, componentId, promoCode, url])

  const renderItem = useCallback(({ item: [key, value], drag, isActive }) => {
    const opacityStyle = { opacity: isActive ? 0.2 : 1 }

    return <Row key={key} style={[styles.row, opacityStyle]} >
      <Column flex={1}>
        <TouchableOpacity style={styles.dragItem} onLongPress={drag}>
          <Column flex={0}>
            <Icon name={Icon.Names.reorderTwoOutline} size={Theme.Sizes.spacing.mdp} color={Theme.Palette.eerieBlack400}/>
          </Column>
          <Column>
            <Text style={styles.itemTitle}>{Localization.translate(`screen_referral__update_landing_page__item__title--${key}`)}</Text>
            <Text style={styles.itemSubTitle}>{Localization.translate(`screen_referral__update_landing_page__item__subtitle--${key}`)}</Text>
          </Column>
        </TouchableOpacity>
      </Column>

      <Column flex={0}>
        <Switch onValueChange={ newValue => onSwitchToggle({ key, value: newValue }) } value={value}/>
      </Column>
    </Row>
  }, [onSwitchToggle])
  return (<>
    <DraggableFlatList
      keyExtractor={keyExtractor}
      dragItemOverflow={false}
      ListHeaderComponent={ListHeaderComponent}
      ItemSeparatorComponent={ItemSeparatorComponent}
      data={sections}
      ListFooterComponent={FooterComponent}
      renderItem={renderItem}
      showsVerticalScrollIndicator={false}
      ListEmptyComponent={ListEmptyComponent}
      onDragEnd={onListOrdered}
      activationDistance={1}
    />
    <ShareCodeCTA loading={loading} code={code} url={url}/>
  </>
  )
}

export default UpdateLandingPage

const styles = StyleSheet.create({
  dragItem: {
    alignItems: 'flex-start',
    display: 'flex',
    flexDirection: 'row',
    paddingLeft: Theme.Sizes.padding.md
  },
  header: {
    marginHorizontal: -Theme.Sizes.margin.md
  },
  horizontalMargin: {
    marginHorizontal: Theme.Sizes.spacing.md
  },
  itemSubTitle: {
    ...Theme.Typography.caption1,
    color: Theme.Palette.eerieBlack600
  },
  itemTitle: {
    ...Theme.Typography.callout,
    ...Theme.FontFamily.medium,
    color: Theme.Palette.eerieBlack800
  },
  link: {
    color: Theme.Palette.violetBlue500
  },
  row: { marginRight: Theme.Sizes.margin.md },
  sectionHeader: {
    paddingHorizontal: 0
  },
  terms: {
    alignContent: 'center',
    marginLeft: Theme.Sizes.margin.md - Theme.Sizes.margin.xs,
    marginTop: Theme.Sizes.margin.xs
  }
})

Platform & Dependencies

TommasoTate commented 3 years ago

seems to be something similar to this one #70

TommasoTate commented 3 years ago

Any update on this one? I could add that, whereas the bug is ever-present in production's build, it pops up in debug only if the app has been open from the launcher, i.e. it disappears if I reload the app from the terminal.

zedelashvililevani commented 3 years ago

same, :facepalm: any updates?

computerjazz commented 3 years ago

I'm guessing this has to do with the fact that your list header is changing size. Can you try updating layoutInvalidationKey with loading, code, and anything else that affects your header size?

brunomartinezciompi commented 3 years ago

@TommasoTate did u manage to solve it? i am having the same issue. Is weird because if I reload the app from the terminal a few times it works.

ithebk commented 3 years ago

Using "react-native-reanimated": "1.13.3" resolved issue for me.

msvickylau commented 3 years ago

Using "react-native-reanimated": "1.13.3" resolved issue for me.

Yes! I had this issue after updating dependencies and fixed it by downgrading react-native-reanimated. v1.13.3 is the latest working version with draggable flatlist. v2 has breaking changes.

melhawnuhra commented 6 months ago

I am getting the same behaviour.

Here is a screen recording demonstrating the problem (on iOS, react-native-draggable-flatlist@4.0.1):

https://github.com/computerjazz/react-native-draggable-flatlist/assets/6492155/b8ecb2bb-6d04-40e6-ad80-edfe7646b60b