/react-native-gallery-toolkit

Reanimated 2 powered gallery implementation

Primary LanguageTypeScriptMIT LicenseMIT

React Native Gallery Toolkit

Reanimated 2 and Gesturer Handler powered Gallery implementation

Gallery in action gif Instagram feed clone

npm

Important!

The library uses Reanimated 2 alpha. It means that it may be unstable. Also, the library itself is in the alpha testing stage and may contain bugs.

Installation

Use npm or yarn to install the library

npm i --save react-native-gallery-toolkit

Also, you need to install react-native-reanimated@2.0.0-alpha.7 (the new 2 version) and react-native-gesture-handler, and follow their installation instructions.

Expo is supported since SDK 40.

npm install react-native-reanimated@2.0.0-rc.0

More information is available https://docs.expo.io/versions/latest/sdk/reanimated/

Standalone gallery

Standalone gallery renders Pager which supports thousands of images thanks to virtualization. Each page renders ImageTransformer component which gives ability to pinch-to-zoom, double tap to zoom, also you can run custom callbacks and worklets on on tab, double tap, pan.

import {
  StandaloneGallery,
  GalleryItemType,
  StandaloneGalleryHandler,
} from 'react-native-gallery-toolkit';

const images: GalleryItemType[] = [
  {
    id: '1',
    width: 300,
    height: 300,
    uri: 'https://placekitten.com/300/300',
  },
  {
    id: '2',
    width: 400,
    height: 200,
    uri: 'https://placekitten.com/400/200',
  },
];

export default function App() {
  return <StandaloneGallery items={images} />;
}

See Full featured example for example of usage of all the props.

Limitations

  • Only portrait orientation currently supported
  • There is no way to change dimensions without full re-render of the gallery
  • Debugging is not supported because of Reanimated v2 uses TurboModules. Use flipper to debug your JS Context.
  • On Android tap on hold on the screen while page changes doesn't trigger animation to stop due to bug in Gesture Handler.

Base props

Prop Description Type Default
items The array of items to render. But can also accept Map, Set, or Object with keys. If the type is not array, then getTotalCount and getItem should be defined too. Array<{ width: number, height: number, id: string, uri: string }> undefined
width? Viewport width number Dimensions.get('window').width
height? Viewport height number Dimensions.get('window').height
numToRender? How many pages should be rendered at the same time number 2
gutterWidth? The width of the gutter between pages number 0
initialIndex? The initial page index number 0
keyExtractor? Callback which extract the key of the page. Receives current item of the provided items as well as current index (item: T, index: number) => string Uses index as a key by default

Advance props

Prop Description Type Default
getTotalCount? If the type of items is not an array, then this method should be defined to provide the total count of items (data: T) => number Required when items is not an array
getItem? If the type of items is not an array, then this method should be defined to provide the current item based on the index. Can return either the item or undefined. (data: T, index: number) => ItemT or undefined Required when items is not an array
renderImage? Callback that can be used to render custom image component. As an example, it can be used to render custom loading/error states (props: RenderImageProps, item: ItemT, index: number) => JSX.Element () => Image
renderPage? Callback that can be used to render custom page. Can be used to display some non-image pages such as Video, for instance (props: ImageRendererProps<T>, index: number) => JSX.Element ImageTransformer

Handlers

Prop Description Type Is worklet? Default
onIndexChange? Fires when active index changes (nextIndex: number) => void Function or Worklet undefined
onTap? Executes when tap image transformer receives tap () => void Function or Worklet undefined
onDoubleTap? Executes when tap image transformer receives double-tap () => void Function or Worklet undefined
onInteraction? Is called when either pan or scale has happened. (type: 'scale' or 'pan') => void Function or Worklet undefined
onPagerTranslateChange? Executes on pager's horizontal pan (translateX: number) => void Function or Worklet undefined
onGesture? Executes on pager's gesture (event: PanGestureHandlerGestureEvent, isActive: SharedValue<boolean>) => void Function or Worklet undefined
shouldPagerHandleGestureEvent? Worklet that will be passed to pager's shouldHandleEvent to determine should pager handle this event. Can be used to handle "swipe down to close". (event: PanGestureHandlerGestureEvent) => boolean Only Worklet undefined

Methods

Name Description Type
goNext Changes the active index forward () => void
goBack Changes the active index backward () => void
setIndex Sets the active index (nextIndex: number) => void

Pager

TODO

Transformer

TODO

Scalable Image

TODO

Examples

The source code for the example (showcase) app is under the Example/ directory. Clone the repo, go to the Example/ folder and run:

npm install

Running on iOS

Before running the app, install the cocoapods dependencies:

npx pod-install

Now, you can start the app:

npm run ios

Running on Android

npm run android

TODOs

  • Add invariants to all the required props
  • Finish documentation
  • Lightbox with examples
  • Lightbox Gallery with examples
  • Try to use react-native-shared-element

LICENSE

MIT