flutter_media_viewer 0.2.0
flutter_media_viewer: ^0.2.0 copied to clipboard
Cached image and video gallery viewer with Hero transitions and playback controls.
flutter_media_viewer #
A cached image and video gallery viewer for Flutter with Hero transitions, playback controls, thumbnails, zoom, swipe-to-dismiss, and metadata details.
Features #
- Displays images and videos in a full-screen gallery.
- Opens with a Hero transition from a ready-to-use preview widget.
- Shares cached network images between previews and the viewer.
- Supports network URLs, file-system paths, and
file:URIs. - Provides video play, pause, seek, mute, autoplay, and looping controls.
- Supports horizontal paging and a centered thumbnail strip.
- Supports pinch-to-zoom for images.
- Dismisses with an animated downward swipe.
- Shows structured technical and location metadata.
- Exposes optional share, delete, header, details, and custom actions.
- Opens as a route or a full-page modal bottom sheet.
- Accepts custom content and thumbnail builders.
- Inherits the active application theme and supports scoped viewer themes.
Installation #
flutter pub add flutter_media_viewer
Import the public library:
import 'package:flutter_media_viewer/flutter_media_viewer.dart';
Quick Start #
Create one or more media items and render a FlutterMediaViewerPreview:
final List<FlutterMediaViewerItem> items = <FlutterMediaViewerItem>[
const FlutterMediaViewerItem.image(
id: 'photo-1',
source: 'https://example.com/photo.jpg',
thumbnailSource: 'https://example.com/photo-thumbnail.jpg',
aspectRatio: 4 / 3,
title: 'Coast',
subtitle: 'Sunday, 4:53 PM',
),
];
FlutterMediaViewerPreview(
items: items,
initialIndex: 0,
borderRadius: BorderRadius.circular(12),
fit: BoxFit.cover,
);
FlutterMediaViewerPreview renders the selected item, owns the Hero transition,
and opens the viewer when tapped. Set useModalBottomSheet to false to open it
as a route instead.
Open Manually #
Use showModal when the preview already handles its own tap gesture:
await FlutterMediaViewer.showModal<void>(
context,
items: items,
initialIndex: selectedIndex,
config: FlutterMediaViewerConfig(
showThumbnails: items.length > 1,
closeTooltip: 'Close',
),
);
Use FlutterMediaViewer.show for route presentation, or place
FlutterMediaViewer directly in an existing widget tree.
Video #
Create a video item with its source and an optional thumbnail:
const FlutterMediaViewerItem.video(
id: 'video-1',
source: 'https://example.com/video.mp4',
thumbnailSource: 'https://example.com/video-thumbnail.jpg',
aspectRatio: 9 / 16,
);
The built-in player pauses when its page is no longer active. Playback behavior
is configured through FlutterMediaViewerConfig:
const FlutterMediaViewerConfig(
enableZoom: false,
enableVideoAutoplay: true,
enableVideoLooping: true,
showVideoControls: true,
startVideosMuted: false,
);
Disable enableZoom for galleries containing videos or custom gesture-heavy
content.
Cached Previews And Placeholders #
Use FlutterMediaPreview when only the media preview is needed. Use
FlutterMediaHero to wrap a completely custom preview while retaining the
viewer transition.
Each item can define cache keys, request headers, and file-system placeholders:
const FlutterMediaViewerItem.image(
id: 'photo-2',
source: 'https://example.com/photo-2.jpg',
thumbnailSource: 'https://example.com/photo-2-thumbnail.jpg',
localPlaceholderSource: '/temporary/photo-2.jpg',
thumbnailLocalPlaceholderSource: '/temporary/photo-2-thumbnail.jpg',
cacheKey: 'photo-2',
thumbnailCacheKey: 'photo-2-thumbnail',
httpHeaders: <String, String>{
'Authorization': 'Bearer token',
},
);
The local placeholder remains visible while the remote source loads and fades smoothly into the cached remote image.
Theming #
The viewer inherits the active ThemeData.colorScheme by default, including
the application's current light or dark mode.
Use themeMode only when a viewer must use a specific brightness independently
from the surrounding application:
const FlutterMediaViewerConfig(
themeMode: ThemeMode.dark,
);
Use FlutterMediaViewerThemeData for a complete per-viewer color scheme:
const FlutterMediaViewerConfig(
theme: FlutterMediaViewerThemeData(
colorScheme: ColorScheme.dark(
primary: Color(0xFF8AB4F8),
),
mediaBackgroundColor: Colors.black,
),
);
Add the same extension to an application's ThemeData.extensions to configure
all viewers under that theme:
ThemeData(
colorScheme: const ColorScheme.dark(),
extensions: const <ThemeExtension<dynamic>>[
FlutterMediaViewerThemeData(
colorScheme: ColorScheme.dark(),
),
],
);
The optional backgroundColor and controlsBackgroundColor configuration
values remain available as focused overrides. Leaving them unset allows the
viewer theme and application color scheme to resolve them.
Relative Sources #
Absolute HTTP(S) URLs are recommended. Relative sources can be resolved with
sourceUrlBuilder:
final FlutterMediaViewerConfig config = FlutterMediaViewerConfig(
sourceUrlBuilder: (String source) {
return Uri.parse('https://cdn.example.com/').resolve(source).toString();
},
);
The same resolver is used for full media and thumbnail sources.
Metadata #
Use FlutterMediaViewerMetadata for the built-in details panel:
const FlutterMediaViewerItem.image(
id: 'photo-3',
source: 'https://example.com/photo-3.jpg',
metadata: FlutterMediaViewerMetadata(
dateText: 'Sunday, September 6, 2026 at 4:53 PM',
fileName: 'IMG_3957.HEIC',
device: 'Phone camera',
format: 'HEIF',
camera: 'Wide camera',
summary: '12 MP - 3024 x 4032 - 3.3 MB',
badges: <String>['LIVE'],
exposure: <String>['ISO 125', '26 mm', 'f/1.8', '1/97 s'],
locationName: 'Coast',
latitude: 37.77,
longitude: -122.42,
),
);
All metadata values are display-ready. Empty fields and sections are omitted. The package validates coordinates but does not extract EXIF data, request location permission, geocode coordinates, or select a map provider.
Use locationPreviewBuilder to render a map preview and onLocationPressed to
handle the location row. Use detailsBuilder to replace the complete details
panel.
A Map<String, String> can be supplied as metadata when a simple list of
localized labels and values is sufficient.
Optional Actions #
Share and delete controls are shown only when their callbacks are configured:
final FlutterMediaViewerConfig config = FlutterMediaViewerConfig(
onSharePressed: handleShare,
onDeletePressed: handleDelete,
);
Callbacks receive the active FlutterMediaViewerOverlayInfo. File sharing,
confirmation, and deletion remain explicit so the package never changes stored
media by itself.
Configuration #
| Option | Default | Description |
|---|---|---|
showControlsInitially |
true |
Shows controls when the viewer opens. |
showThumbnails |
true |
Shows thumbnail navigation for galleries. |
showHeader |
true |
Shows non-empty item titles and subtitles. |
showCloseButton |
true |
Shows the platform-aware back button. |
enableSwipeDownToDismiss |
true |
Enables downward drag dismissal. |
backgroundColor |
null |
Overrides the media background, which defaults to black. |
controlsBackgroundColor |
null |
Overrides the themed controls and details surface. |
themeMode |
null |
Optionally forces light, dark, or system brightness. |
theme |
null |
Overrides the inherited FlutterMediaViewerThemeData. |
constrainedMediaBorderRadius |
24 px |
Radius applied only when tall media is constrained. |
imageFit |
BoxFit.contain |
Fit used by built-in media. |
thumbnailFit |
BoxFit.cover |
Fit used by built-in thumbnails. |
enableZoom |
true |
Enables InteractiveViewer. |
minScale |
1 |
Minimum zoom scale. |
maxScale |
4 |
Maximum zoom scale. |
enableVideoAutoplay |
true |
Autoplays the active video. |
enableVideoLooping |
true |
Loops built-in videos. |
showVideoControls |
true |
Shows playback, timeline, and mute controls. |
startVideosMuted |
false |
Starts built-in videos muted. |
showBottomActionBar |
true |
Allows configured bottom actions. |
sourceUrlBuilder |
null |
Resolves relative sources. |
topActionsBuilder |
null |
Builds additional top actions. |
bottomActionsBuilder |
null |
Builds additional bottom actions. |
onSharePressed |
null |
Shows and handles the share action. |
onDeletePressed |
null |
Shows and handles the delete action. |
detailsBuilder |
null |
Replaces the details panel. |
locationPreviewBuilder |
null |
Builds an optional location preview. |
onLocationPressed |
null |
Handles the location row. |
All visible labels and tooltips can be supplied through
FlutterMediaViewerConfig for localization.
Custom Content #
Use the base FlutterMediaViewerItem constructor with contentBuilder and
thumbnailBuilder for unsupported formats, DRM, or specialized rendering.
Built-in image and video rendering is used when those builders are omitted.
Layout Behavior #
Pass the media width-to-height aspectRatio whenever it is available. The
built-in image and video renderers can resolve it after loading when omitted.
Tall media is constrained only when its full-width height would overlap the top
or bottom controls. Its intrinsic aspect ratio determines the resulting width,
with rounded corners and a subtle border in that constrained state. Media that
fits remains full width. Opening details expands the active media over the
available upper area with BoxFit.cover; closing details restores its previous
frame and fit.
Example #
The example directory demonstrates images, videos, metadata, thumbnails,
custom builders, actions, and both presentation modes.
License #
MIT License. See LICENSE.