Skip to content

Commit

Permalink
Support image long press handler (#36)
Browse files Browse the repository at this point in the history
* Support image long press handler

* wrap onLongPressHandler with useCallback

Co-authored-by: Maxim Bolshakov <maksimko@gmail.com>
  • Loading branch information
nojimage and maksimko committed May 3, 2020
1 parent f57a73f commit f5508f7
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 7 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ const [visible, setIsVisible] = useState(false);
| `visible` | Is modal shown or not | boolean | true |
| `onRequestClose` | Function called to close the modal | function | true |
| `onImageIndexChange` | Function called when image index has been changed | function | false |
| `onLongPress` | Function called when image long pressed | function (event: GestureResponderEvent, image: ImageSource) | false |
| `delayLongPress` | Delay in ms, before onLongPress is called: default `800` | number | false |
| `animationType` | Animation modal presented with: default `fade` | `none`, `fade`, `slide` | false |
| `presentationStyle` | Modal presentation style: default: `fullScreen` **Android:** Use `overFullScreen` to hide StatusBar | `fullScreen`, `pageSheet`, `formSheet`, `overFullScreen` | false |
| `backgroundColor` | Background color of the modal in HEX (#000000EE) | string | false |
Expand Down
5 changes: 5 additions & 0 deletions example/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import React, { useState } from "react";
import {
Alert,
Platform,
SafeAreaView,
StatusBar,
Expand Down Expand Up @@ -43,6 +44,9 @@ export default function App() {
const getImageUrls = memoize((images) =>
images.map((image) => ({ uri: image.original as string }))
);
const onLongPress = (event, image) => {
Alert.alert('Long Pressed', image.uri);
};

return (
<SafeAreaView style={styles.root}>
Expand All @@ -65,6 +69,7 @@ export default function App() {
presentationStyle="overFullScreen"
visible={isVisible}
onRequestClose={onRequestClose}
onLongPress={onLongPress}
HeaderComponent={
images === travel
? ({ imageIndex }) => {
Expand Down
8 changes: 8 additions & 0 deletions src/ImageViewing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
View,
VirtualizedList,
ModalProps,
GestureResponderEvent,
} from "react-native";

import Modal from "./components/Modal/Modal";
Expand All @@ -30,18 +31,21 @@ type Props = {
imageIndex: number;
visible: boolean;
onRequestClose: () => void;
onLongPress?: (event: GestureResponderEvent, image: ImageSource) => void;
onImageIndexChange?: (imageIndex: number) => void;
presentationStyle?: ModalProps["presentationStyle"];
animationType?: ModalProps["animationType"];
backgroundColor?: string;
swipeToCloseEnabled?: boolean;
doubleTapToZoomEnabled?: boolean;
delayLongPress?: number;
HeaderComponent?: ComponentType<{ imageIndex: number }>;
FooterComponent?: ComponentType<{ imageIndex: number }>;
};

const DEFAULT_ANIMATION_TYPE = "fade";
const DEFAULT_BG_COLOR = "#000";
const DEFAULT_DELAY_LONG_PRESS = 800;
const SCREEN = Dimensions.get("screen");
const SCREEN_WIDTH = SCREEN.width;

Expand All @@ -50,12 +54,14 @@ function ImageViewing({
imageIndex,
visible,
onRequestClose,
onLongPress = () => {},
onImageIndexChange,
animationType = DEFAULT_ANIMATION_TYPE,
backgroundColor = DEFAULT_BG_COLOR,
presentationStyle,
swipeToCloseEnabled,
doubleTapToZoomEnabled,
delayLongPress= DEFAULT_DELAY_LONG_PRESS,
HeaderComponent,
FooterComponent,
}: Props) {
Expand Down Expand Up @@ -125,6 +131,8 @@ function ImageViewing({
onZoom={onZoom}
imageSrc={imageSrc}
onRequestClose={onRequestCloseEnhanced}
onLongPress={onLongPress}
delayLongPress={delayLongPress}
swipeToCloseEnabled={swipeToCloseEnabled}
doubleTapToZoomEnabled={doubleTapToZoomEnabled}
/>
Expand Down
30 changes: 24 additions & 6 deletions src/components/ImageItem/ImageItem.android.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import {
StyleSheet,
NativeScrollEvent,
NativeSyntheticEvent,
TouchableWithoutFeedback,
GestureResponderEvent,
} from "react-native";

import useImageDimensions from "../../hooks/useImageDimensions";
Expand All @@ -33,6 +35,8 @@ type Props = {
imageSrc: ImageSource;
onRequestClose: () => void;
onZoom: (isZoomed: boolean) => void;
onLongPress: (event: GestureResponderEvent, image: ImageSource) => void;
delayLongPress: number;
swipeToCloseEnabled?: boolean;
doubleTapToZoomEnabled?: boolean;
};
Expand All @@ -41,6 +45,8 @@ const ImageItem = ({
imageSrc,
onZoom,
onRequestClose,
onLongPress,
delayLongPress,
swipeToCloseEnabled = true,
doubleTapToZoomEnabled = true,
}: Props) => {
Expand Down Expand Up @@ -101,6 +107,13 @@ const ImageItem = ({
scrollValueY.setValue(offsetY);
};

const onLongPressHandler = useCallback(
(event: GestureResponderEvent) => {
onLongPress(event, imageSrc);
},
[]
);

return (
<Animated.ScrollView
ref={imageContainer}
Expand All @@ -116,12 +129,17 @@ const ImageItem = ({
onScrollEndDrag,
})}
>
<Animated.Image
{...panHandlers}
source={imageSrc}
style={imageStylesWithOpacity}
onLoad={onLoaded}
/>
<TouchableWithoutFeedback
onLongPress={onLongPressHandler}
delayLongPress={delayLongPress}
>
<Animated.Image
{...panHandlers}
source={imageSrc}
style={imageStylesWithOpacity}
onLoad={onLoaded}
/>
</TouchableWithoutFeedback>
{(!isLoaded || !imageDimensions) && <ImageLoading />}
</Animated.ScrollView>
);
Expand Down
7 changes: 6 additions & 1 deletion src/components/ImageItem/ImageItem.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@
*/

import React from "react";
import { GestureResponderEvent } from "react-native";
import { ImageSource } from "../../@types";

declare type Props = {
imageSrc: ImageSource;
onRequestClose: () => void;
onZoom: (isZoomed: boolean) => void;
onLongPress: (event: GestureResponderEvent, image: ImageSource) => void;
delayLongPress: number;
swipeToCloseEnabled?: boolean;
doubleTapToZoomEnabled?: boolean;
};
Expand All @@ -21,7 +24,9 @@ declare const _default: React.MemoExoticComponent<({
imageSrc,
onZoom,
onRequestClose,
swipeToCloseEnabled,
onLongPress,
delayLongPress,
swipeToCloseEnabled
}: Props) => JSX.Element>;

export default _default;
14 changes: 14 additions & 0 deletions src/components/ImageItem/ImageItem.ios.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
NativeScrollEvent,
NativeSyntheticEvent,
TouchableWithoutFeedback,
GestureResponderEvent,
} from "react-native";

import useDoubleTapToZoom from "../../hooks/useDoubleTapToZoom";
Expand All @@ -36,6 +37,8 @@ type Props = {
imageSrc: ImageSource;
onRequestClose: () => void;
onZoom: (scaled: boolean) => void;
onLongPress: (event: GestureResponderEvent, image: ImageSource) => void;
delayLongPress: number;
swipeToCloseEnabled?: boolean;
doubleTapToZoomEnabled?: boolean;
};
Expand All @@ -44,6 +47,8 @@ const ImageItem = ({
imageSrc,
onZoom,
onRequestClose,
onLongPress,
delayLongPress,
swipeToCloseEnabled = true,
doubleTapToZoomEnabled = true,
}: Props) => {
Expand Down Expand Up @@ -101,6 +106,13 @@ const ImageItem = ({
scrollValueY.setValue(offsetY);
};

const onLongPressHandler = useCallback(
(event: GestureResponderEvent) => {
onLongPress(event, imageSrc);
},
[]
);

return (
<View>
<ScrollView
Expand All @@ -122,6 +134,8 @@ const ImageItem = ({
{(!loaded || !imageDimensions) && <ImageLoading />}
<TouchableWithoutFeedback
onPress={doubleTapToZoomEnabled ? handleDoubleTap : undefined}
onLongPress={onLongPressHandler}
delayLongPress={delayLongPress}
>
<Animated.Image
source={imageSrc}
Expand Down

0 comments on commit f5508f7

Please sign in to comment.