flutter_ios_preview 1.0.0 copy "flutter_ios_preview: ^1.0.0" to clipboard
flutter_ios_preview: ^1.0.0 copied to clipboard

A premium Flutter tool for high-fidelity iOS simulation. Featuring the curated iphone Collection, dynamic notch/island hardware, and proportional scaling for cross-platform design testing.

example/lib/main.dart

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

void main() {
  runApp(const ExampleApp());
}

class ExampleApp extends StatefulWidget {
  const ExampleApp({super.key});

  @override
  State<ExampleApp> createState() => _ExampleAppState();
}

class _ExampleAppState extends State<ExampleApp> {
  // Flagship default: iPhone 16 Pro Max (6.9")
  DeviceModel _selectedModel = DeviceModel.iPhone16ProMax;
  bool _enableInspector = true;
  bool _useFrame = true;
  bool _showPreview = true;

  // Explicit controller to resolve the 'Attached to more than one ScrollView' conflict
  final ScrollController _mainScrollController = ScrollController();

  @override
  void dispose() {
    _mainScrollController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        useMaterial3: true,
        colorSchemeSeed: const Color(0xFF007AFF),
      ),
      home: Builder(
        builder: (context) => Scaffold(
          appBar: AppBar(
            title: const Text('iOS Hub'),
            actions: [
              IconButton(
                icon: Icon(
                  _showPreview ? Icons.visibility_off : Icons.visibility,
                ),
                onPressed: () => setState(() => _showPreview = !_showPreview),
                tooltip: 'Toggle Preview',
              ),
            ],
          ),
          drawer: _buildSettingsDrawer(),
          body: _showPreview
              ? IosPreview(
                  deviceModel: _selectedModel,
                  enableInspector: _enableInspector,
                  useFrame: _useFrame,
                  child: MySampleApp(controller: _mainScrollController),
                )
              : MySampleApp(controller: _mainScrollController),
          floatingActionButton: (_showPreview && _useFrame)
              ? FloatingActionButton(
                  child: const Icon(Icons.camera_alt),
                  onPressed: () async {
                    final path = await ScreenshotHandler.captureAndSave(
                      IosPreview.boundaryKey,
                    );
                    if (path != null && context.mounted) {
                      ScaffoldMessenger.of(context).showSnackBar(
                        SnackBar(content: Text('Screenshot saved: $path')),
                      );
                    }
                  },
                )
              : null,
        ),
      ),
    );
  }

  Widget _buildSettingsDrawer() {
    return Drawer(
      child: Column(
        children: [
          const DrawerHeader(
            decoration: BoxDecoration(
              gradient: LinearGradient(
                colors: [Color(0xFF000000), Color(0xFF1A1A1A)],
                begin: Alignment.topLeft,
                end: Alignment.bottomRight,
              ),
            ),
            child: Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Icon(Icons.apple, color: Colors.white, size: 48),
                  SizedBox(height: 8),
                  Text(
                    'IOS COLLECTION',
                    style: TextStyle(
                      color: Colors.white,
                      fontSize: 18,
                      fontWeight: FontWeight.bold,
                      letterSpacing: 1,
                    ),
                  ),
                  Text(
                    'Elite Flagship Simulator',
                    style: TextStyle(color: Colors.white70, fontSize: 12),
                  ),
                ],
              ),
            ),
          ),
          Expanded(
            child: ListView(
              padding: EdgeInsets.zero,
              children: [
                SwitchListTile(
                  title: const Text('Device Frame'),
                  subtitle: Text(
                    _useFrame
                        ? 'Showing Flagship Frame'
                        : 'Full Screen Simulation',
                  ),
                  value: _useFrame,
                  onChanged: (v) => setState(() => _useFrame = v),
                ),
                const Divider(),
                Padding(
                  padding: const EdgeInsets.symmetric(
                    horizontal: 16,
                    vertical: 8,
                  ),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      const Text(
                        'FLAGSHIP GENERATION',
                        style: TextStyle(
                          fontSize: 11,
                          fontWeight: FontWeight.bold,
                          color: Colors.blueAccent,
                        ),
                      ),
                      const SizedBox(height: 8),
                      Container(
                        padding: const EdgeInsets.symmetric(horizontal: 12),
                        decoration: BoxDecoration(
                          color: Colors.white,
                          border: Border.all(color: Colors.grey[300]!),
                          borderRadius: BorderRadius.circular(12),
                        ),
                        child: DropdownButtonHideUnderline(
                          child: DropdownButton<DeviceModel>(
                            value: _selectedModel,
                            isExpanded: true,
                            borderRadius: BorderRadius.circular(12),
                            onChanged: (m) =>
                                setState(() => _selectedModel = m!),
                            items: DeviceModel.values.map((m) {
                              final isSE = m.name.contains('SE');
                              return DropdownMenuItem(
                                value: m,
                                child: Text(
                                  m.name,
                                  style: TextStyle(
                                    fontWeight: m.name.contains('Max')
                                        ? FontWeight.bold
                                        : FontWeight.normal,
                                    color: isSE
                                        ? Colors.deepOrange
                                        : Colors.black87,
                                  ),
                                ),
                              );
                            }).toList(),
                          ),
                        ),
                      ),
                    ],
                  ),
                ),
                _buildDeviceSpecs(),
                const Divider(),
                SwitchListTile(
                  title: const Text('Widget Inspector'),
                  subtitle: const Text('Analyze elite UI metrics'),
                  value: _enableInspector,
                  onChanged: (v) => setState(() => _enableInspector = v),
                ),
                const Divider(),
                const AboutListTile(
                  icon: Icon(Icons.info_outline),
                  applicationName: 'Flutter iOS Preview',
                  applicationVersion: '1.0.0 (Flagship Edition)',
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildDeviceSpecs() {
    final info = DeviceInfo.fromModel(_selectedModel);
    final isUltra =
        _selectedModel.name.contains('16') ||
        _selectedModel.name.contains('17') ||
        _selectedModel.name.contains('18');

    return Container(
      margin: const EdgeInsets.all(16),
      padding: const EdgeInsets.all(16),
      decoration: BoxDecoration(
        color: isUltra ? Colors.blue.withAlpha(10) : Colors.grey[50],
        borderRadius: BorderRadius.circular(16),
        border: Border.all(
          color: isUltra ? Colors.blue.withAlpha(40) : Colors.grey[200]!,
        ),
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Row(
            children: [
              Icon(
                isUltra
                    ? Icons.workspace_premium
                    : Icons.dashboard_customize_outlined,
                size: 16,
                color: isUltra ? Colors.blue : Colors.blueAccent,
              ),
              const SizedBox(width: 8),
              Text(
                isUltra ? 'ULTRA-MAX SPECS' : 'FLAGSHIP SPECS',
                style: TextStyle(
                  fontSize: 12,
                  fontWeight: FontWeight.bold,
                  color: isUltra ? Colors.blue : Colors.blueAccent,
                ),
              ),
            ],
          ),
          const SizedBox(height: 12),
          _specRow('Model', _selectedModel.name),
          _specRow(
            'Logical Size',
            '${info.screenSize.width.toInt()} x ${info.screenSize.height.toInt()}',
          ),
          _specRow('Top Inset', '${info.safeArea.top.toInt()}pt'),
          _specRow('Side Insets', '${info.landscapeSideInset.toInt()}pt'),
          _specRow('Bezel Width', '${info.bezelThickness}pt'),
          _specRow('Curvature', '${info.cornerRadius.toInt()}pt'),
          if (info.category == DeviceCategory.dynamicIsland)
            _specRow(
              'Island Width',
              '${info.islandWidth.toInt()}pt',
              isHighlight: _selectedModel == DeviceModel.iPhone18ProMax,
            ),
        ],
      ),
    );
  }

  Widget _specRow(String label, String value, {bool isHighlight = false}) {
    return Padding(
      padding: const EdgeInsets.only(bottom: 6),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          Text(label, style: const TextStyle(fontSize: 11, color: Colors.grey)),
          Text(
            value,
            style: TextStyle(
              fontSize: 11,
              fontWeight: FontWeight.bold,
              color: isHighlight ? Colors.blue : Colors.black87,
            ),
          ),
        ],
      ),
    );
  }
}

class MySampleApp extends StatelessWidget {
  final ScrollController? controller;
  const MySampleApp({super.key, this.controller});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Pro Max Flagship'),
        centerTitle: true,
        backgroundColor: Colors.white,
        elevation: 0,
        leading: const Icon(Icons.menu, color: Colors.black),
        actions: const [
          Icon(Icons.shopping_bag_outlined, color: Colors.black),
          SizedBox(width: 16),
        ],
      ),
      body: CustomScrollView(
        controller: controller,
        slivers: [
          SliverToBoxAdapter(
            child: Padding(
              padding: const EdgeInsets.all(24),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  const Text(
                    'iPhone 18 Pro Max',
                    style: TextStyle(
                      fontSize: 14,
                      fontWeight: FontWeight.bold,
                      color: Colors.blueAccent,
                    ),
                  ),
                  const Text(
                    'Big. Bold. Brilliant.',
                    style: TextStyle(
                      fontSize: 36,
                      fontWeight: FontWeight.w900,
                      letterSpacing: -1,
                    ),
                  ),
                  const SizedBox(height: 12),
                  const Text(
                    'Experience the elite 6.9-inch flagship simulation.',
                    style: TextStyle(color: Colors.grey, fontSize: 16),
                  ),
                  const SizedBox(height: 24),
                  _buildClassicCard(
                    'Ultra Power.',
                    'Titanium Refined.',
                    Colors.black,
                  ),
                ],
              ),
            ),
          ),
          SliverPadding(
            padding: const EdgeInsets.symmetric(horizontal: 24),
            sliver: SliverList(
              delegate: SliverChildBuilderDelegate(
                (context, index) => _buildProductItem(index),
                childCount: 8,
              ),
            ),
          ),
        ],
      ),
      bottomNavigationBar: BottomNavigationBar(
        elevation: 10,
        selectedItemColor: Colors.blueAccent,
        unselectedItemColor: Colors.grey,
        items: const [
          BottomNavigationBarItem(
            icon: Icon(Icons.shop_outlined),
            label: 'Shop',
          ),
          BottomNavigationBarItem(icon: Icon(Icons.search), label: 'Search'),
          BottomNavigationBarItem(
            icon: Icon(Icons.person_pin),
            label: 'Account',
          ),
        ],
      ),
    );
  }

  Widget _buildClassicCard(String title, String subtitle, Color bgColor) {
    return Container(
      width: double.infinity,
      height: 380,
      decoration: BoxDecoration(
        color: bgColor,
        borderRadius: BorderRadius.circular(32),
        boxShadow: [
          BoxShadow(
            color: Colors.black.withAlpha(77),
            blurRadius: 20,
            offset: const Offset(0, 10),
          ),
        ],
      ),
      child: Stack(
        children: [
          Positioned(
            top: 50,
            left: 30,
            right: 30,
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                Text(
                  title,
                  style: const TextStyle(
                    color: Colors.white,
                    fontSize: 40,
                    fontWeight: FontWeight.w900,
                  ),
                ),
                const SizedBox(height: 10),
                Text(
                  subtitle,
                  style: const TextStyle(color: Colors.white70, fontSize: 18),
                  textAlign: TextAlign.center,
                ),
              ],
            ),
          ),
          const Positioned(
            bottom: -20,
            left: 0,
            right: 0,
            child: Center(
              child: Icon(Icons.auto_awesome, size: 220, color: Colors.white10),
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildProductItem(int index) {
    return Container(
      margin: const EdgeInsets.only(bottom: 16),
      padding: const EdgeInsets.all(20),
      decoration: BoxDecoration(
        color: Colors.grey[100],
        borderRadius: BorderRadius.circular(20),
      ),
      child: Row(
        children: [
          Container(
            width: 60,
            height: 60,
            decoration: BoxDecoration(
              color: Colors.white,
              borderRadius: BorderRadius.circular(16),
            ),
            child: const Icon(Icons.star_outline, color: Colors.blueAccent),
          ),
          const SizedBox(width: 20),
          const Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  'Pro Max Feature',
                  style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18),
                ),
                Text(
                  'Elite precision simulation.',
                  style: TextStyle(color: Colors.grey, fontSize: 13),
                ),
              ],
            ),
          ),
          const Icon(Icons.arrow_forward_ios, color: Colors.grey, size: 14),
        ],
      ),
    );
  }
}
5
likes
140
points
78
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A premium Flutter tool for high-fidelity iOS simulation. Featuring the curated iphone Collection, dynamic notch/island hardware, and proportional scaling for cross-platform design testing.

Repository (GitHub)
View/report issues

Topics

#ios #preview #simulator #iphone #ui-development

License

MIT (license)

Dependencies

flutter, gal, path_provider

More

Packages that depend on flutter_ios_preview