react-native-image-zoom icon indicating copy to clipboard operation
react-native-image-zoom copied to clipboard

Prevent FlatList scrolling while image zoomed

Open Stmol opened this issue 7 years ago • 15 comments

Hi! I have a FlatList with items wrapped to ImageZoom:

<FlatList
     horizontal
     pagingEnabled={true}
     showsHorizontalScrollIndicator={false}

     data={this.props.images}
     renderItem={item => this.renderImage(item)}
/>

And the render image function is:

renderImage = ({item}) => {
    return (
      <View style={{width: SCREEN_WIDTH, height: 'auto'}}>
        <ImageZoom
          cropWidth={Dimensions.get('window').width}
          cropHeight={Dimensions.get('window').height}
          imageWidth={Dimensions.get('window').width}
          imageHeight={'100%'}
        >
          <FastImage
            resizeMode={FastImage.resizeMode.contain}
            source={{uri: item.source.uri, cache: 'force-cache'}}
          />
        </ImageZoom>
      </View>
    )
  }

But as I starting zoom an image, the FlatList trying to scroll to next (or previous) page. How to prevent the FlatList responding to gestures while Image are zooming?

Stmol avatar Feb 06 '18 19:02 Stmol

@Stmol Are you seeing this on Android too? I have the reverse issue on Android: When using this control in a carousel, the carousel doesn't scroll anymore because the zoom control takes all the gestures.

hardcodet avatar Feb 17 '18 17:02 hardcodet

https://www.npmjs.com/package/react-native-image-gallery

ashrithks avatar Mar 09 '18 13:03 ashrithks

I am facing the same issue in android. My scrolling view stops scrolling. ImageZoom took charge of scrolling. Can we still achieve scrolling with zoom in app.?

Please let me know.

ios-dev-newbie avatar Mar 29 '18 14:03 ios-dev-newbie

same here,

https://github.com/ascoders/react-native-image-viewer/blob/master/src/image-viewer.component.tsx uses this library and doesn't seem to have the problem..

littlehome-eugene avatar Sep 04 '18 05:09 littlehome-eugene

@littlehome-eugene great, are there any other questions?

ascoders avatar Sep 04 '18 06:09 ascoders

Well but the library I mentioned doesn't use flatlist, I'd like to know if it's possible to use flatlist as a wrapper as OP asked

littlehome-eugene avatar Sep 04 '18 06:09 littlehome-eugene

I'm not tried yet, but it's seem possible to replace Animated.View with FlatList in react-native-image-zoom-viewer, welcome pr!

ascoders avatar Sep 04 '18 06:09 ascoders

Yeah seems possible, but doesn't work, ImageZoom took charge of scrolling. as @stmol and @ios-dev-newbie has reported.

littlehome-eugene avatar Sep 04 '18 06:09 littlehome-eugene

There's a lengthy discussion on this topic..

https://github.com/archriss/react-native-snap-carousel/issues/264

littlehome-eugene avatar Sep 04 '18 08:09 littlehome-eugene

I am also facing the same issue mentioned by @ios-dev-newbie ? Please help

hanishcodebrew avatar Oct 26 '18 09:10 hanishcodebrew

My solution:

const [scroll, setScroll] = useState(true);

<Flatlist
    ...
    scrollEnabled={scroll}
    renderItem={({ item }) =>
          <ImageZoom
                   ...
                   panToMove={!scroll}
                   onMove={({ scale }) => { setScroll(scale === 1 ? true : false) }}
                   <Image
                   ...
                   />
           </ImageZoom>}
/>

Dror-Bar avatar Aug 25 '19 08:08 Dror-Bar

The solution above not worked well on Android.

So I upgraded ImageZoom into the code below.

And it works well now.

const ImageViewer: FC<ImageViewerProps> = ({
  source,
  width = Dimensions.get('window').width,
  height = Dimensions.get('window').height,
  onMove,
  ...props
}) => {
  const scaleValue = useRef(1);
  return (
    <ImageZoom
      cropWidth={Dimensions.get('window').width}
      cropHeight={Dimensions.get('window').height}
      imageWidth={width}
      imageHeight={height}
      minScale={1}
      {...props}
      onStartShouldSetPanResponder={(e) => {
        return e.nativeEvent.touches.length === 2 || scaleValue.current > 1;
      }}
      onMove={({scale}) => {
        scaleValue.current = scale;
        onMove && onMove({scale});
      }}>
      <View
        style={{width: '100%', height: '100%'}}
        onStartShouldSetResponder={(e) => {
          return e.nativeEvent.touches.length < 2 && scaleValue.current <= 1;
        }}>
        <Image
          source={source}
          resizeMode="contain"
          style={{width: '100%', height: '100%'}}
        />
      </View>
    </ImageZoom>
  );
};

darron1217 avatar Nov 26 '20 10:11 darron1217

const ImageViewer: FC<ImageViewerProps> = ({
  source,
  width = Dimensions.get('window').width,
  height = Dimensions.get('window').height,
  onMove,
  ...props
}) => {
  const scaleValue = useRef(1);
  return (
    <ImageZoom
      cropWidth={Dimensions.get('window').width}
      cropHeight={Dimensions.get('window').height}
      imageWidth={width}
      imageHeight={height}
      minScale={1}
      {...props}
      onStartShouldSetPanResponder={(e) => {
        return e.nativeEvent.touches.length === 2 || scaleValue.current > 1;
      }}
      onMove={({scale}) => {
        scaleValue.current = scale;
        onMove && onMove({scale});
      }}>
      <View
        style={{width: '100%', height: '100%'}}
        onStartShouldSetResponder={(e) => {
          console.log(
            scaleValue.current,
            e.nativeEvent.touches.length < 2 && scaleValue.current <= 1,
          );
          return e.nativeEvent.touches.length < 2 && scaleValue.current <= 1;
        }}>
        <Image
          source={source}
          resizeMode="contain"
          style={{width: '100%', height: '100%'}}
        />
      </View>
    </ImageZoom>
  );
};

Thanks a lot , it worked 👍

DonOzOn avatar Dec 09 '20 17:12 DonOzOn

The solution above not worked well on Android.

So I upgraded ImageZoom into the code below.

And it works well now.

const ImageViewer: FC<ImageViewerProps> = ({
  source,
  width = Dimensions.get('window').width,
  height = Dimensions.get('window').height,
  onMove,
  ...props
}) => {
  const scaleValue = useRef(1);
  return (
    <ImageZoom
      cropWidth={Dimensions.get('window').width}
      cropHeight={Dimensions.get('window').height}
      imageWidth={width}
      imageHeight={height}
      minScale={1}
      {...props}
      onStartShouldSetPanResponder={(e) => {
        return e.nativeEvent.touches.length === 2 || scaleValue.current > 1;
      }}
      onMove={({scale}) => {
        scaleValue.current = scale;
        onMove && onMove({scale});
      }}>
      <View
        style={{width: '100%', height: '100%'}}
        onStartShouldSetResponder={(e) => {
          console.log(
            scaleValue.current,
            e.nativeEvent.touches.length < 2 && scaleValue.current <= 1,
          );
          return e.nativeEvent.touches.length < 2 && scaleValue.current <= 1;
        }}>
        <Image
          source={source}
          resizeMode="contain"
          style={{width: '100%', height: '100%'}}
        />
      </View>
    </ImageZoom>
  );
};

You save my life, thank you so much!!!!!

Quang-Dong avatar Jan 20 '21 06:01 Quang-Dong

The solution above not worked well on Android.

So I upgraded ImageZoom into the code below.

And it works well now.

const ImageViewer: FC<ImageViewerProps> = ({
  source,
  width = Dimensions.get('window').width,
  height = Dimensions.get('window').height,
  onMove,
  ...props
}) => {
  const scaleValue = useRef(1);
  return (
    <ImageZoom
      cropWidth={Dimensions.get('window').width}
      cropHeight={Dimensions.get('window').height}
      imageWidth={width}
      imageHeight={height}
      minScale={1}
      {...props}
      onStartShouldSetPanResponder={(e) => {
        return e.nativeEvent.touches.length === 2 || scaleValue.current > 1;
      }}
      onMove={({scale}) => {
        scaleValue.current = scale;
        onMove && onMove({scale});
      }}>
      <View
        style={{width: '100%', height: '100%'}}
        onStartShouldSetResponder={(e) => {
          return e.nativeEvent.touches.length < 2 && scaleValue.current <= 1;
        }}>
        <Image
          source={source}
          resizeMode="contain"
          style={{width: '100%', height: '100%'}}
        />
      </View>
    </ImageZoom>
  );
};

Thanks for this! Appreciate it!

castalonirenz avatar May 10 '21 17:05 castalonirenz