device_lab 0.2.0 copy "device_lab: ^0.2.0" to clipboard
device_lab: ^0.2.0 copied to clipboard

Preview your Flutter app on any device without a simulator: 149 devices, foldables with real display features, free-form resolutions, and golden-test integration.

example/lib/main.dart

import 'package:device_lab/device_lab.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(
    DeviceLab(
      initialDeviceId: 'apple.iphone-duo',
      restoreButtonAlignment: Alignment.bottomLeft,
      availableLocales: const [Locale('en'), Locale('ja'), Locale('ar')],
      builder: (_) => const DemoApp(),
    ),
  );
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      builder: DeviceLab.appBuilder,
      locale: DeviceLab.localeOf(context),
      theme: ThemeData(
        useMaterial3: true,
        colorScheme: ColorScheme.fromSeed(seedColor: const Color(0xFF00897B)),
      ),
      darkTheme: ThemeData(
        useMaterial3: true,
        colorScheme: ColorScheme.fromSeed(
          seedColor: const Color(0xFF00897B),
          brightness: Brightness.dark,
        ),
      ),
      themeMode: ThemeMode.system,
      home: const HomePage(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    final media = MediaQuery.of(context);
    final fold = media.separatingFold;

    return Scaffold(
      appBar: AppBar(title: const Text('device_lab demo')),
      floatingActionButton: FloatingActionButton(
        onPressed: () {},
        child: const Icon(Icons.add),
      ),
      body: fold == null
          ? _Panel(media: media)
          : Row(
              children: [
                Expanded(child: _Panel(media: media)),
                const VerticalDivider(width: 1),
                const Expanded(child: _DetailPane()),
              ],
            ),
    );
  }
}

class _Panel extends StatelessWidget {
  const _Panel({required this.media});

  final MediaQueryData media;

  @override
  Widget build(BuildContext context) {
    return ListView(
      padding: const EdgeInsets.all(16),
      children: [
        Card(
          child: Padding(
            padding: const EdgeInsets.all(16),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  'Viewport',
                  style: Theme.of(context).textTheme.titleMedium,
                ),
                const SizedBox(height: 8),
                _Row(
                    'size',
                    '${media.size.width.toStringAsFixed(0)} × '
                        '${media.size.height.toStringAsFixed(0)} dp'),
                _Row('dpr', '${media.devicePixelRatio}'),
                _Row('padding', media.padding.toString()),
                _Row('textScale', media.textScaler.scale(1).toStringAsFixed(2)),
                _Row('platform', Theme.of(context).platform.name),
                _Row('features', '${media.displayFeatures.length}'),
              ],
            ),
          ),
        ),
        const SizedBox(height: 16),
        for (var i = 0; i < 8; i++)
          ListTile(
            leading: CircleAvatar(child: Text('${i + 1}')),
            title: Text('Item ${i + 1}'),
            subtitle: const Text('Scroll physics follow the device platform'),
          ),
      ],
    );
  }
}

class _DetailPane extends StatelessWidget {
  const _DetailPane();

  @override
  Widget build(BuildContext context) => const Center(
        child: Padding(
          padding: EdgeInsets.all(24),
          child: Text(
            'Two-pane layout\nselected by the fold display feature',
            textAlign: TextAlign.center,
          ),
        ),
      );
}

class _Row extends StatelessWidget {
  const _Row(this.label, this.value);

  final String label;
  final String value;

  @override
  Widget build(BuildContext context) => Padding(
        padding: const EdgeInsets.symmetric(vertical: 2),
        child: Row(
          children: [
            SizedBox(width: 90, child: Text(label)),
            Expanded(
              child: Text(
                value,
                style: const TextStyle(fontFamilyFallback: ['monospace']),
              ),
            ),
          ],
        ),
      );
}
3
likes
0
points
273
downloads

Publisher

unverified uploader

Weekly Downloads

Preview your Flutter app on any device without a simulator: 149 devices, foldables with real display features, free-form resolutions, and golden-test integration.

Repository (GitHub)
View/report issues

Topics

#responsive #preview #devtools #testing #foldable

License

unknown (license)

Dependencies

flutter, flutter_test

More

Packages that depend on device_lab