For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /guide/usage/custom-components.md.
v3 is stable. See what changed
  • English
  • 3.x
  • Custom Components

    react-native-gesture-image-viewer offers powerful complete component customization. You can create gesture-supported items with not only images but any component you want.

    You can create a viewer using any Modal of your choice as shown below:

    Use Modal
    Use react-nativee-modal
    import { Image, Modal } from 'react-native';
    import { GestureViewer } from 'react-native-gesture-image-viewer';
    
    function App() {
      const images = [...];
      const [visible, setVisible] = useState(false);
    
      return (
        <Modal visible={visible} onRequestClose={() => setVisible(false)}>
          <GestureViewer
            data={images}
            renderItem={renderImage}
            onDismiss={() => setVisible(false)}
          />
        </Modal>
      );
    }

    Render Window

    Version 3 uses an internal render window instead of a consumer-supplied list component. Use renderItem for content customization, and tune windowSize or pageSpacing only when the default window is not enough.

    function App() {
      return <GestureViewer data={images} renderItem={renderImage} windowSize={5} pageSpacing={16} />;
    }

    Content Components

    You can inject various types of content components like expo-image, FastImage, etc., through the renderItem prop to use gestures.

    import { GestureViewer } from 'react-native-gesture-image-viewer';
    import { Image } from 'expo-image';
    
    const images = [
      'https://images.unsplash.com/photo-1682687220742-aba13b6e50ba',
      'https://images.unsplash.com/photo-1682687220063-4742bd7fd538',
      'https://images.unsplash.com/photo-1682687218147-9806132dc697',
    ];
    
    function renderImage(imageUrl: string) {
      return (
        <Image
          source={{ uri: imageUrl }}
          style={{ width: '100%', height: '100%' }}
          contentFit="contain"
        />
      );
    }
    
    function App() {
      return <GestureViewer data={images} renderItem={renderImage} />;
    }

    For accurate zoom and pan bounds with contain content, see the item dimensions guide.

    renderItem active state (isActive)

    For content such as video that should play or perform work only while it is visible, use isActive from the third renderItem argument. It is true only for the currently selected content. During a page transition, the previous content remains active; when the move finishes, the newly selected content becomes active. Use useGestureViewerState instead when UI outside the item needs the global currentIndex.

    import { GestureViewer, type GestureViewerRenderItemInfo } from 'react-native-gesture-image-viewer';
    import Video from 'react-native-video';
    
    type MediaItem = {
      id: string;
      uri: string;
    };
    
    const mediaItems: MediaItem[] = [
      {
        id: 'video-1',
        uri: 'https://www.w3schools.com/html/mov_bbb.mp4',
      },
      {
        id: 'video-2',
        uri: 'https://www.w3schools.com/html/movie.mp4',
      },
    ];
    
    function renderMedia(item: MediaItem, _index: number, { isActive }: GestureViewerRenderItemInfo) {
      return (
        <Video
          source={{ uri: item.uri }}
          style={{ width: '100%', height: '100%' }}
          paused={!isActive}
          resizeMode="contain"
        />
      );
    }
    
    function App() {
      return <GestureViewer data={mediaItems} renderItem={renderMedia} />;
    }