flutter_widget_inspector 0.1.0 copy "flutter_widget_inspector: ^0.1.0" to clipboard
flutter_widget_inspector: ^0.1.0 copied to clipboard

A runtime Flutter widget inspector — long-press to activate, tap any widget to see its render type, size, position, constraints, padding, text style, and decoration. Works without modifying your widget tree.

example/lib/main.dart

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

void main() => runApp(const InspectorExampleApp());

/// Root application for the flutter_widget_inspector example.
///
/// [WidgetInspectorWrapper] is placed around the home page so that any widget
/// on that page can be inspected at runtime.
///
/// **How to use:**
/// 1. Run on a device or simulator — `flutter run`
/// 2. Long-press anywhere to activate inspect mode (blue badge appears)
/// 3. Tap any widget to see its layout info
/// 4. Drag the info panel to reposition it
/// 5. Tap ✕ to deselect; long-press again to exit inspect mode
class InspectorExampleApp extends StatelessWidget {
  const InspectorExampleApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Widget Inspector Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(colorScheme: ColorScheme.fromSeed(seedColor: const Color(0xFF6750A4)), useMaterial3: true),
      home: const WidgetInspectorWrapper(
        // kDebugMode ensures zero overhead in release builds.
        enabled: kDebugMode,
        child: _DemoPage(),
      ),
    );
  }
}

// ---------------------------------------------------------------------------
// _DemoPage
// ---------------------------------------------------------------------------

class _DemoPage extends StatefulWidget {
  const _DemoPage();

  @override
  State<_DemoPage> createState() => _DemoPageState();
}

class _DemoPageState extends State<_DemoPage> {
  int _counter = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: const Color(0xFFF5F5F7),
      appBar: AppBar(
        backgroundColor: Colors.white,
        elevation: 0,
        title: const Text('Widget Inspector Demo', style: TextStyle(fontWeight: FontWeight.w600)),
        bottom: PreferredSize(
          preferredSize: const Size.fromHeight(1),
          child: Container(height: 1, color: Colors.black12),
        ),
      ),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(20),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            // ── Instructions ──────────────────────────────────────────────────
            const _InstructionBanner(),
            const SizedBox(height: 24),

            // ── Coloured cards ────────────────────────────────────────────────
            const _SectionTitle('Cards & Containers'),
            const SizedBox(height: 12),
            const Row(
              children: [
                Expanded(
                  child: _ColorCard(color: Color(0xFF6750A4), label: 'Purple'),
                ),
                SizedBox(width: 12),
                Expanded(
                  child: _ColorCard(color: Color(0xFF006874), label: 'Teal'),
                ),
                SizedBox(width: 12),
                Expanded(
                  child: _ColorCard(color: Color(0xFFB3261E), label: 'Red'),
                ),
              ],
            ),
            const SizedBox(height: 24),

            // ── Buttons ───────────────────────────────────────────────────────
            const _SectionTitle('Buttons'),
            const SizedBox(height: 12),
            Wrap(
              spacing: 10,
              runSpacing: 10,
              children: [
                ElevatedButton(onPressed: () {}, child: const Text('Elevated')),
                OutlinedButton(onPressed: () {}, child: const Text('Outlined')),
                TextButton(onPressed: () {}, child: const Text('Text')),
                FilledButton(onPressed: () {}, child: const Text('Filled')),
                FilledButton.tonal(onPressed: () {}, child: const Text('Tonal')),
              ],
            ),
            const SizedBox(height: 24),

            // ── Counter ───────────────────────────────────────────────────────
            const _SectionTitle('Stateful Counter'),
            const SizedBox(height: 12),
            _CounterCard(
              count: _counter,
              onIncrement: () => setState(() => _counter++),
              onDecrement: () => setState(() => _counter--),
            ),
            const SizedBox(height: 24),

            // ── Typography ────────────────────────────────────────────────────
            const _SectionTitle('Typography'),
            const SizedBox(height: 12),
            const Card(
              margin: EdgeInsets.zero,
              child: Padding(
                padding: EdgeInsets.all(16),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text('Display Large', style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold)),
                    SizedBox(height: 8),
                    Text('Headline Medium', style: TextStyle(fontSize: 18, fontWeight: FontWeight.w600)),
                    SizedBox(height: 8),
                    Text('Body text — long-press anywhere to start inspecting.'),
                    SizedBox(height: 8),
                    Text('Caption text', style: TextStyle(fontSize: 11, color: Colors.grey)),
                  ],
                ),
              ),
            ),
            const SizedBox(height: 24),

            // ── Icons ─────────────────────────────────────────────────────────
            const _SectionTitle('Icons & Avatars'),
            const SizedBox(height: 12),
            Wrap(
              spacing: 12,
              runSpacing: 12,
              children: [
                for (final entry in {
                  Icons.favorite: Colors.red,
                  Icons.star: Colors.amber,
                  Icons.bolt: Colors.orange,
                  Icons.eco: Colors.green,
                  Icons.water_drop: Colors.blue,
                  Icons.local_fire_department: Colors.deepOrange,
                }.entries)
                  CircleAvatar(
                    backgroundColor: entry.value.withValues(alpha: 0.12),
                    child: Icon(entry.key, color: entry.value),
                  ),
              ],
            ),
            const SizedBox(height: 24),

            // ── Nested containers ─────────────────────────────────────────────
            const _SectionTitle('Nested Containers'),
            const SizedBox(height: 12),
            Container(
              padding: const EdgeInsets.all(16),
              decoration: BoxDecoration(
                color: Colors.indigo.shade50,
                borderRadius: BorderRadius.circular(12),
                border: Border.all(color: Colors.indigo.shade200),
              ),
              child: Column(
                children: [
                  Container(
                    height: 40,
                    color: Colors.indigo.shade100,
                    alignment: Alignment.center,
                    child: const Text('Inner box 1', style: TextStyle(fontSize: 12)),
                  ),
                  const SizedBox(height: 8),
                  Row(
                    children: [
                      Expanded(
                        child: Container(
                          height: 40,
                          color: Colors.indigo.shade200,
                          alignment: Alignment.center,
                          child: const Text('2a', style: TextStyle(fontSize: 12)),
                        ),
                      ),
                      const SizedBox(width: 8),
                      Expanded(
                        flex: 2,
                        child: Container(
                          height: 40,
                          color: Colors.indigo.shade300,
                          alignment: Alignment.center,
                          child: const Text('2b (flex 2)', style: TextStyle(fontSize: 12)),
                        ),
                      ),
                    ],
                  ),
                ],
              ),
            ),
            const SizedBox(height: 80),
          ],
        ),
      ),
    );
  }
}

// ---------------------------------------------------------------------------
// Small reusable demo components
// ---------------------------------------------------------------------------

class _InstructionBanner extends StatelessWidget {
  const _InstructionBanner();

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.all(14),
      decoration: BoxDecoration(
        gradient: const LinearGradient(colors: [Color(0xFF6750A4), Color(0xFF9C27B0)]),
        borderRadius: BorderRadius.circular(12),
      ),
      child: const Row(
        children: [
          Icon(Icons.touch_app, color: Colors.white, size: 28),
          SizedBox(width: 12),
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  '🔍 How to use',
                  style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 13),
                ),
                SizedBox(height: 4),
                Text(
                  'Long-press anywhere to activate inspector mode, '
                  'then tap any widget.',
                  style: TextStyle(color: Colors.white70, fontSize: 11),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

class _SectionTitle extends StatelessWidget {
  final String title;
  const _SectionTitle(this.title);

  @override
  Widget build(BuildContext context) {
    return Text(
      title,
      style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w600, color: Colors.black54),
    );
  }
}

class _ColorCard extends StatelessWidget {
  final Color color;
  final String label;

  const _ColorCard({required this.color, required this.label});

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 80,
      decoration: BoxDecoration(color: color, borderRadius: BorderRadius.circular(12)),
      alignment: Alignment.center,
      child: Text(
        label,
        style: const TextStyle(color: Colors.white, fontWeight: FontWeight.w600, fontSize: 12),
      ),
    );
  }
}

class _CounterCard extends StatelessWidget {
  final int count;
  final VoidCallback onIncrement;
  final VoidCallback onDecrement;

  const _CounterCard({required this.count, required this.onIncrement, required this.onDecrement});

  @override
  Widget build(BuildContext context) {
    return Card(
      margin: EdgeInsets.zero,
      child: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            IconButton(
              onPressed: onDecrement,
              icon: const Icon(Icons.remove_circle_outline),
              color: Theme.of(context).colorScheme.error,
            ),
            Column(
              children: [
                Text('$count', style: const TextStyle(fontSize: 36, fontWeight: FontWeight.bold)),
                const Text('counter', style: TextStyle(fontSize: 11, color: Colors.grey)),
              ],
            ),
            IconButton(
              onPressed: onIncrement,
              icon: const Icon(Icons.add_circle_outline),
              color: Theme.of(context).colorScheme.primary,
            ),
          ],
        ),
      ),
    );
  }
}
4
likes
150
points
92
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A runtime Flutter widget inspector — long-press to activate, tap any widget to see its render type, size, position, constraints, padding, text style, and decoration. Works without modifying your widget tree.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

flutter

More

Packages that depend on flutter_widget_inspector