skeleton_builder 0.0.1 copy "skeleton_builder: ^0.0.1" to clipboard
skeleton_builder: ^0.0.1 copied to clipboard

A Flutter package for creating beautiful, animated skeleton loading screens with minimal code. Supports lists, grids, forms, and auto-detection of layouts.

example/lib/main.dart

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

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

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

  @override
  State<SkeletonExampleApp> createState() => _SkeletonExampleAppState();
}

class _SkeletonExampleAppState extends State<SkeletonExampleApp> {
  ThemeMode _themeMode = ThemeMode.light;

  void _toggleTheme() {
    setState(() {
      _themeMode =
          _themeMode == ThemeMode.light ? ThemeMode.dark : ThemeMode.light;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      themeMode: _themeMode,
      theme: ThemeData.light(useMaterial3: true),
      darkTheme: ThemeData.dark(useMaterial3: true),
      home: HomePage(onToggleTheme: _toggleTheme),
    );
  }
}

class HomePage extends StatelessWidget {
  final VoidCallback onToggleTheme;

  const HomePage({super.key, required this.onToggleTheme});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Skeleton Builder Demo'),
        actions: [
          IconButton(
            icon: const Icon(Icons.brightness_6),
            onPressed: onToggleTheme,
          ),
        ],
      ),
      body: ListView(
        padding: const EdgeInsets.all(16),
        children: [
          _DemoCard(
            title: 'List Skeleton',
            subtitle: 'Animated loading skeleton for lists',
            icon: Icons.list,
            color: Colors.blue,
            onTap: () => Navigator.push(
              context,
              MaterialPageRoute(
                builder: (_) => ListSkeletonScreen(onToggleTheme: onToggleTheme),
              ),
            ),
          ),
          const SizedBox(height: 12),
          _DemoCard(
            title: 'Grid Skeleton',
            subtitle: 'Animated loading skeleton for grids',
            icon: Icons.grid_view,
            color: Colors.green,
            onTap: () => Navigator.push(
              context,
              MaterialPageRoute(
                builder: (_) => GridSkeletonScreen(onToggleTheme: onToggleTheme),
              ),
            ),
          ),
          const SizedBox(height: 12),
          _DemoCard(
            title: 'Form Skeleton',
            subtitle: 'Animated loading skeleton for forms',
            icon: Icons.article,
            color: Colors.orange,
            onTap: () => Navigator.push(
              context,
              MaterialPageRoute(
                builder: (_) => FormSkeletonScreen(onToggleTheme: onToggleTheme),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

class _DemoCard extends StatelessWidget {
  final String title;
  final String subtitle;
  final IconData icon;
  final Color color;
  final VoidCallback onTap;

  const _DemoCard({
    required this.title,
    required this.subtitle,
    required this.icon,
    required this.color,
    required this.onTap,
  });

  @override
  Widget build(BuildContext context) {
    return Card(
      clipBehavior: Clip.antiAlias,
      child: InkWell(
        onTap: onTap,
        child: Padding(
          padding: const EdgeInsets.all(16),
          child: Row(
            children: [
              Container(
                padding: const EdgeInsets.all(12),
                decoration: BoxDecoration(
                  color: color.withValues(alpha: 0.1),
                  borderRadius: BorderRadius.circular(12),
                ),
                child: Icon(icon, color: color, size: 32),
              ),
              const SizedBox(width: 16),
              Expanded(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      title,
                      style: Theme.of(context).textTheme.titleMedium?.copyWith(
                            fontWeight: FontWeight.bold,
                          ),
                    ),
                    const SizedBox(height: 4),
                    Text(
                      subtitle,
                      style: Theme.of(context).textTheme.bodySmall,
                    ),
                  ],
                ),
              ),
              const Icon(Icons.chevron_right),
            ],
          ),
        ),
      ),
    );
  }
}

// ============================================================
// LIST SKELETON SCREEN
// ============================================================
class ListSkeletonScreen extends StatefulWidget {
  final VoidCallback onToggleTheme;

  const ListSkeletonScreen({super.key, required this.onToggleTheme});

  @override
  State<ListSkeletonScreen> createState() => _ListSkeletonScreenState();
}

class _ListSkeletonScreenState extends State<ListSkeletonScreen> {
  bool _isLoading = true;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('List Skeleton'),
        actions: [
          IconButton(
            icon: const Icon(Icons.brightness_6),
            onPressed: widget.onToggleTheme,
          ),
          IconButton(
            icon: Icon(_isLoading ? Icons.visibility : Icons.visibility_off),
            onPressed: () => setState(() => _isLoading = !_isLoading),
          ),
        ],
      ),
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: _isLoading
            ? const SkeletonList(itemCount: 8)
            : ListView.separated(
                itemCount: 8,
                separatorBuilder: (_, __) => const SizedBox(height: 12),
                itemBuilder: (_, i) => ListTile(
                  leading: CircleAvatar(child: Text('${i + 1}')),
                  title: Text('List Item ${i + 1}'),
                  subtitle: const Text('This is the loaded content'),
                  tileColor: Theme.of(context).colorScheme.surfaceContainerHighest,
                  shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(12),
                  ),
                ),
              ),
      ),
    );
  }
}

// ============================================================
// GRID SKELETON SCREEN
// ============================================================
class GridSkeletonScreen extends StatefulWidget {
  final VoidCallback onToggleTheme;

  const GridSkeletonScreen({super.key, required this.onToggleTheme});

  @override
  State<GridSkeletonScreen> createState() => _GridSkeletonScreenState();
}

class _GridSkeletonScreenState extends State<GridSkeletonScreen> {
  bool _isLoading = true;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Grid Skeleton'),
        actions: [
          IconButton(
            icon: const Icon(Icons.brightness_6),
            onPressed: widget.onToggleTheme,
          ),
          IconButton(
            icon: Icon(_isLoading ? Icons.visibility : Icons.visibility_off),
            onPressed: () => setState(() => _isLoading = !_isLoading),
          ),
        ],
      ),
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: _isLoading
            ? const SkeletonGrid(
                crossAxisCount: 2,
                itemCount: 6,
                itemHeight: 150,
              )
            : GridView.builder(
                itemCount: 6,
                gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                  crossAxisCount: 2,
                  crossAxisSpacing: 12,
                  mainAxisSpacing: 12,
                ),
                itemBuilder: (_, i) => Card(
                  clipBehavior: Clip.antiAlias,
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Icon(
                        Icons.image,
                        size: 48,
                        color: Theme.of(context).colorScheme.primary,
                      ),
                      const SizedBox(height: 8),
                      Text(
                        'Card ${i + 1}',
                        style: Theme.of(context).textTheme.titleMedium,
                      ),
                    ],
                  ),
                ),
              ),
      ),
    );
  }
}

// ============================================================
// FORM SKELETON SCREEN
// ============================================================
class FormSkeletonScreen extends StatefulWidget {
  final VoidCallback onToggleTheme;

  const FormSkeletonScreen({super.key, required this.onToggleTheme});

  @override
  State<FormSkeletonScreen> createState() => _FormSkeletonScreenState();
}

class _FormSkeletonScreenState extends State<FormSkeletonScreen> {
  bool _isLoading = true;

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context).brightness == Brightness.dark
        ? SkeletonTheme.dark()
        : SkeletonTheme.light();

    return Scaffold(
      appBar: AppBar(
        title: const Text('Form Skeleton'),
        actions: [
          IconButton(
            icon: const Icon(Icons.brightness_6),
            onPressed: widget.onToggleTheme,
          ),
          IconButton(
            icon: Icon(_isLoading ? Icons.visibility : Icons.visibility_off),
            onPressed: () => setState(() => _isLoading = !_isLoading),
          ),
        ],
      ),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(16),
        child: _isLoading
            ? SkeletonForm(fieldCount: 4, theme: theme)
            : Column(
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: [
                  TextField(
                    decoration: InputDecoration(
                      labelText: 'Full Name',
                      border: OutlineInputBorder(
                        borderRadius: BorderRadius.circular(8),
                      ),
                    ),
                  ),
                  const SizedBox(height: 16),
                  TextField(
                    decoration: InputDecoration(
                      labelText: 'Email Address',
                      border: OutlineInputBorder(
                        borderRadius: BorderRadius.circular(8),
                      ),
                    ),
                  ),
                  const SizedBox(height: 16),
                  TextField(
                    decoration: InputDecoration(
                      labelText: 'Phone Number',
                      border: OutlineInputBorder(
                        borderRadius: BorderRadius.circular(8),
                      ),
                    ),
                  ),
                  const SizedBox(height: 16),
                  TextField(
                    maxLines: 3,
                    decoration: InputDecoration(
                      labelText: 'Message',
                      border: OutlineInputBorder(
                        borderRadius: BorderRadius.circular(8),
                      ),
                    ),
                  ),
                  const SizedBox(height: 24),
                  FilledButton(
                    onPressed: () {},
                    style: FilledButton.styleFrom(
                      padding: const EdgeInsets.symmetric(vertical: 16),
                      shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(12),
                      ),
                    ),
                    child: const Text('Submit'),
                  ),
                ],
              ),
      ),
    );
  }
}
1
likes
150
points
188
downloads

Publisher

verified publisherdivyanshdev.tech

Weekly Downloads

A Flutter package for creating beautiful, animated skeleton loading screens with minimal code. Supports lists, grids, forms, and auto-detection of layouts.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

flutter

More

Packages that depend on skeleton_builder