alhilali_device_preview

pub package

Preview your Flutter app inside realistic device frames, switch devices/orientation/system settings, and export clean marketing screenshots from one package.

alhilali_device_preview is a maintained fork of the original MIT-licensed device_preview package. This fork focuses on compatibility with recent Flutter releases, realistic device frames, and transparent framed PNG exports.

Features

  • Preview your app on phones, tablets, desktops, and custom devices.
  • Use realistic device frames from the same public import.
  • Switch orientation, locale, theme, text scale, accessibility flags, and virtual keyboard state.
  • Keep app state while changing preview settings.
  • Export transparent framed screenshots without installing a second package.
  • Save screenshots automatically to a user-accessible location.

Install

Add one dependency:

dependencies:
  alhilali_device_preview: ^1.4.0

Then import it:

import 'package:alhilali_device_preview/alhilali_device_preview.dart';

This single import includes Device Preview, device frame APIs, and screenshot export tools.

Basic Usage

Wrap your app with DevicePreview in main.dart.

import 'package:alhilali_device_preview/alhilali_device_preview.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(
    DevicePreview(
      enabled: !kReleaseMode,
      builder: (context) => const MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      locale: DevicePreview.locale(context),
      builder: DevicePreview.appBuilder,
      theme: ThemeData.light(),
      darkTheme: ThemeData.dark(),
      home: const HomePage(),
    );
  }
}

DevicePreview.appBuilder applies the simulated media query, theme, text scale, safe areas, and other preview values to your app.

Screenshot Export

Add DevicePreviewScreenshot to the tool list. No extra package is required.

import 'package:alhilali_device_preview/alhilali_device_preview.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(
    DevicePreview(
      enabled: !kReleaseMode,
      tools: const [
        ...DevicePreview.defaultTools,
        DevicePreviewScreenshot(
          pixelRatio: 4,
          multipleScreenshots: true,
        ),
      ],
      builder: (context) => const MyApp(),
    ),
  );
}

Open the Device Preview toolbar, then click Export transparent PNG.

The exported image includes:

  • the device frame
  • screen content
  • bezels
  • notches and dynamic islands
  • visible frame decorations

The exported image excludes:

  • editor background
  • Device Preview workspace background
  • app canvas outside the device frame
  • toolbars and overlays outside the previewed device

Where Screenshots Are Saved

By default, DevicePreviewScreenshot() saves the PNG automatically in a user-accessible location:

  • Android: Pictures/DevicePreviewExports
  • Windows, macOS, and Linux: device_preview_exports in the current working directory
  • Other dart:io platforms: device_preview_exports inside the app documents directory

The tool shows a SnackBar with the saved path after export.

If The Button Does Not Appear

Check these points:

  • DevicePreviewScreenshot() is inside DevicePreview.tools.
  • ...DevicePreview.defaultTools is still included if you want the default controls.
  • DevicePreview is enabled. If you use enabled: !kReleaseMode, the UI appears only outside release builds.
  • The app was restarted after changing dependencies or imports.

Android Permissions

The default Android export uses media_store_plus internally and writes to Pictures/DevicePreviewExports. Modern Android versions usually do not need an extra permission prompt for this save flow.

If your app needs to support older Android versions, especially Android 9/API 28 or below, add the legacy storage permissions in android/app/src/main/AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
    <uses-permission
        android:name="android.permission.READ_EXTERNAL_STORAGE"
        android:maxSdkVersion="32" />
    <uses-permission
        android:name="android.permission.WRITE_EXTERNAL_STORAGE"
        android:maxSdkVersion="29" />

    <application
        android:requestLegacyExternalStorage="true"
        ...>
    </application>
</manifest>

For most new apps, no custom MediaStore code is needed.

Custom Save Directory

The automatic saver is the default. If you want to save to a specific writable directory, pass screenshotAsFiles:

import 'dart:io';

import 'package:alhilali_device_preview/alhilali_device_preview.dart';

final outputDirectory = Directory('screenshots')..createSync(recursive: true);

DevicePreviewScreenshot(
  pixelRatio: 4,
  onScreenshot: screenshotAsFiles(outputDirectory),
)

Custom Processing

You can upload screenshots, save them to cloud storage, attach them to test reports, or process them in memory by providing your own ScreenshotProcessor.

DevicePreviewScreenshot(
  onScreenshot: (context, screenshot) async {
    final bytes = screenshot.bytes;
    final device = screenshot.device;
    // Save, upload, or transform bytes here.
  },
)

Use Device Frames Directly

The same package exports DeviceFrame, DeviceInfo, and Devices:

import 'package:alhilali_device_preview/alhilali_device_preview.dart';

DeviceFrame(
  device: Devices.ios.iPhone16ProMax,
  screen: const MyScreen(),
)

Use Custom Devices

You can add your own device definitions:

DevicePreview(
  devices: [
    ...Devices.ios.all,
    DeviceInfo.genericPhone(
      platform: TargetPlatform.android,
      name: 'Marketing Phone',
      id: 'marketing-phone',
      screenSize: const Size(430, 932),
      pixelRatio: 3,
      safeAreas: const EdgeInsets.only(top: 44, bottom: 34),
      rotatedSafeAreas: const EdgeInsets.symmetric(horizontal: 44),
    ),
  ],
  builder: (context) => const MyApp(),
)

Use Device Preview only in debug/profile builds:

DevicePreview(
  enabled: !kReleaseMode,
  builder: (context) => const MyApp(),
)

You can also disable it with a compile-time flag:

DevicePreview(
  enabled: const bool.fromEnvironment('DEVICE_PREVIEW', defaultValue: true),
  builder: (context) => const MyApp(),
)

Run with:

flutter run --dart-define=DEVICE_PREVIEW=false

Example

This repository includes a complete example for transparent PNG export:

examples/transparent_png_export_example

It demonstrates:

  • DevicePreview
  • DevicePreviewScreenshot
  • high-resolution transparent PNG export
  • automatic saving to a user-accessible export folder

Limitations

Device Preview approximates how your app appears on another device. It does not replace testing on real devices, especially for platform APIs, performance, camera, sensors, permissions, native views, and store-specific screenshot requirements.

License

MIT. Original copyright notices are preserved.