react-native-gallery-picker-pro
Version:
A comprehensive React Native media gallery picker with smooth animations, multi-select, single-select, crop functionality, and native iOS/Android support
236 lines (184 loc) • 6.85 kB
Markdown
with smooth animations, multi-select/single-select modes, crop functionality, and native iOS/Android support.
- 🖼️ **Modern UI** - Smooth scrolling with layered animations
- 📱 **Native Performance** - Built with native iOS and Android modules
- ✨ **Multi/Single Select** - Flexible selection modes
- ✂️ **Crop Functionality** - Built-in image cropping with aspect ratio controls
- 🎬 **Video Support** - Handle both images and videos
- 🎯 **Gesture Controls** - Intuitive touch gestures and animations
- 📐 **Aspect Ratios** - Support for multiple aspect ratios (0.8, 16:9, 1:1)
- 🔄 **Permission Handling** - Smart permission management
- 📤 **Export Options** - Base64, URI, and file data support
## Installation
```bash
npm install motorinc-media-picker
```
### iOS Setup
1. Add to your `Podfile`:
```ruby
pod 'MotorincMediaPicker', :path => '../node_modules/motorinc-media-picker'
```
2. Run:
```bash
cd ios && pod install
```
The Android module is automatically linked with React Native 0.60+.
Make sure you have these peer dependencies installed:
```bash
npm install react-native-gesture-handler react-native-reanimated react-native-view-shot
```
Follow the setup instructions for:
- [react-native-gesture-handler](https://docs.swmansion.com/react-native-gesture-handler/docs/installation)
- [react-native-reanimated](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/getting-started)
```jsx
import React from 'react';
import { View } from 'react-native';
import { MainPhotoGallery } from 'motorinc-media-picker';
export default function App() {
const handleAssetSelected = (asset) => {
console.log('Selected asset:', asset);
};
const handleSelectedAssetsChange = (assets) => {
console.log('Selected assets:', assets);
};
return (
<View style={{ flex: 1 }}>
<MainPhotoGallery
mediaType="all"
multiSelect={true}
maxSelectionLimit={10}
onAssetSelected={handleAssetSelected}
onSelectedAssetsChange={handleSelectedAssetsChange}
/>
</View>
);
}
```
```jsx
import React, { useRef, useState } from 'react';
import { View, Button } from 'react-native';
import { MainPhotoGallery } from 'motorinc-media-picker';
export default function App() {
const galleryRef = useRef(null);
const [selectedAssets, setSelectedAssets] = useState([]);
const [cropParams, setCropParams] = useState(new Map());
const handleCroppedImagesReady = (croppedImages) => {
console.log('Cropped images:', croppedImages);
};
const handleCropCapture = async () => {
if (galleryRef.current) {
await galleryRef.current.triggerCropCapture();
}
};
return (
<View style={{ flex: 1 }}>
<MainPhotoGallery
ref={galleryRef}
mediaType="image"
multiSelect={true}
selectedAssets={selectedAssets}
onSelectedAssetsChange={setSelectedAssets}
showSelectedAssetsHeader={true}
onCropParamsChange={(assetId, params) => {
setCropParams(prev => new Map(prev.set(assetId, params)));
}}
existingCropParams={cropParams}
onCroppedImagesReady={handleCroppedImagesReady}
onAspectRatioChange={(ratio) => console.log('Aspect ratio:', ratio)}
/>
<Button title="Capture Cropped Images" onPress={handleCropCapture} />
</View>
);
}
```
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `mediaType` | `'image' \| 'video' \| 'all'` | `'all'` | Type of media to display |
| `multiSelect` | `boolean` | `false` | Enable multi-selection mode |
| `maxSelectionLimit` | `number` | `10` | Maximum number of assets that can be selected |
| `selectedAssets` | `PhotoAsset[]` | `[]` | Currently selected assets |
| `onAssetSelected` | `(asset: PhotoAsset) => void` | - | Callback when a single asset is selected |
| `onSelectedAssetsChange` | `(assets: PhotoAsset[]) => void` | - | Callback when selected assets change |
| `showSelectedAssetsHeader` | `boolean` | `false` | Show cropping header for selected assets |
| `hideSelectionHeader` | `boolean` | `false` | Hide the selection mode header |
| `onCropParamsChange` | `(assetId: string, params: CropParams \| null) => void` | - | Callback for crop parameter changes |
| `existingCropParams` | `Map<string, CropParams>` | - | Existing crop parameters |
| `onAspectRatioChange` | `(ratio: number) => void` | - | Callback for aspect ratio changes |
| `onCroppedImagesReady` | `(images: Array<{assetId: string, dataUri: string}>) => void` | - | Callback when cropped images are ready |
| `onCancel` | `() => void` | - | Cancel button callback |
| `onNext` | `(assets: PhotoAsset[]) => void` | - | Next button callback |
| `renderPermissionDeniedState` | `(onRequest?: () => void) => React.ReactNode` | - | Custom permission denied state |
```typescript
interface PhotoAsset {
id: string;
uri: string;
filename: string;
width: number;
height: number;
creationDate: number;
mediaType: 'image' | 'video';
duration?: number; // For videos
}
```
```typescript
interface CropParams {
x: number;
y: number;
width: number;
height: number;
scale: number;
aspectRatio: number;
}
```
```typescript
interface SelectedImage {
uri: string;
fileName: string;
fileSize: number;
width: number;
height: number;
type: string;
id: string;
base64: string;
}
```
The gallery implements smooth layered scroll behavior:
- **Scroll Up**: First hides the header section, then allows grid scrolling
- **Scroll Down**: Grid scrolls down immediately, regardless of header position
- **Header Drag**: Can always drag header up/down to show/hide sections
- **Smooth Animations**: Cubic easing for natural feel
Add to your `Info.plist`:
```xml
<key>NSPhotoLibraryUsageDescription</key>
<string>This app needs access to photo library to select images</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>This app needs access to save images to photo library</string>
```
Add to your `AndroidManifest.xml`:
```xml
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
```
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
MIT
If you like this project, please consider giving it a ⭐ on GitHub!
A comprehensive React Native media gallery picker