โœจ Skeletonizer Plus

pub package License: MIT CI

Production-quality skeleton loading states with automatic generation, shimmer animations, and performance optimizations

Transform your app's loading experience with intelligent skeleton screens that automatically adapt to your widgets. skeletonizer_plus provides a comprehensive solution for creating beautiful, performant loading states that match your UI perfectly.

โœจ What Makes This Package Special?

This isn't just another shimmer loader. We've built a complete solution that combines:

  • ๐ŸŽจ Automatic Skeleton Generation: Intelligently introspects your widget trees to generate skeleton "bones" that match your UI structure
  • ๐ŸŽญ Custom Bone Layouts: Create precise skeleton layouts with predefined bone types (text, circles, rectangles, icons)
  • โœจ Beautiful Shimmer Animations: Smooth, configurable shimmer effects with multiple directions and customizable colors
  • ๐ŸŒ“ Smart Theme Integration: Automatically adapts to light/dark themes with appropriate colors
  • โšก Performance Optimized: Built-in optimizations for large lists and complex layouts
  • ๐Ÿ“ฑ Sliver Support: Seamless integration with CustomScrollView and sliver-based widgets

Perfect for social media feeds, e-commerce product lists, news articles, or any app that needs professional loading states.

๐Ÿš€ Quick Start

Installation

Add skeletonizer_plus to your pubspec.yaml:

dependencies:
  skeletonizer_plus: ^1.0.0

Then run:

flutter pub get

Basic Usage

Wrap any widget with SkeletonizerPlus to automatically generate skeleton bones:

import 'package:skeletonizer_plus/skeletonizer_plus.dart';

SkeletonizerPlus(
  enabled: isLoading,
  child: ListView.builder(
    itemCount: items.length,
    itemBuilder: (context, index) => Card(
      child: ListTile(
        leading: CircleAvatar(child: Icon(Icons.person)),
        title: Text(items[index].title),
        subtitle: Text(items[index].subtitle),
      ),
    ),
  ),
)

That's it! The package automatically detects your widgets and creates matching skeleton bones.

๐ŸŽจ Features in Detail

Automatic Skeleton Generation

The package intelligently analyzes your widget tree and generates skeleton bones that match your UI:

SkeletonizerPlus(
  enabled: isLoading,
  child: Card(
    child: Column(
      children: [
        CircleAvatar(child: Icon(Icons.person)),  // โ†’ BoneCircle
        Text('John Doe'),                          // โ†’ BoneText
        Text('Software Engineer'),                 // โ†’ BoneText
        Image.network('...'),                      // โ†’ BoneRect
      ],
    ),
  ),
)

The analyzer automatically detects:

  • Text widgets โ†’ BoneText with appropriate word count
  • Icons โ†’ BoneIcon with matching size
  • Images โ†’ BoneRect with rounded corners
  • Containers/Cards โ†’ BoneRect with appropriate border radius
  • ListTiles โ†’ Multiple bones for leading, title, and subtitle

Custom Bone Layouts

For precise control, create custom skeleton layouts:

SkeletonizerPlus.custom(
  enabled: isLoading,
  bones: [
    BoneCircle(radius: 30),
    BoneText(words: 4, lines: 2),
    BoneRect(width: 200, height: 100, radius: 12),
    BoneIcon(size: 32),
  ],
  baseColor: Colors.grey[300],
  highlightColor: Colors.grey[100],
  speed: Duration(milliseconds: 1200),
)

Shimmer Animations

Beautiful, smooth shimmer effects with full customization:

SkeletonizerPlus(
  enabled: isLoading,
  baseColor: Colors.blue[200],
  highlightColor: Colors.blue[50],
  speed: Duration(milliseconds: 800),
  direction: ShimmerDirection.ltr,  // ltr, rtl, topDown, bottomUp
  loop: true,                        // Infinite loop
  child: YourWidget(),
)

Sliver Support

Perfect for scrollable content with CustomScrollView:

CustomScrollView(
  slivers: [
    SliverSkeletonizerPlus(
      enabled: isLoading,
      child: SliverList(
        delegate: SliverChildBuilderDelegate(
          (context, index) => ListTile(title: Text('Item $index')),
          childCount: items.length,
        ),
      ),
    ),
  ],
)

๐Ÿ’ก Real-World Use Cases

Social Media Feed

SkeletonizerPlus(
  enabled: isLoading,
  child: ListView.builder(
    itemCount: posts.length,
    itemBuilder: (context, index) => Card(
      child: Column(
        children: [
          ListTile(
            leading: CircleAvatar(...),
            title: Text(posts[index].author),
            subtitle: Text(posts[index].time),
          ),
          Image.network(posts[index].imageUrl),
          Padding(
            padding: EdgeInsets.all(16),
            child: Text(posts[index].caption),
          ),
        ],
      ),
    ),
  ),
)

E-commerce Product List

SkeletonizerPlus(
  enabled: isLoading,
  child: GridView.builder(
    gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
      crossAxisCount: 2,
    ),
    itemBuilder: (context, index) => ProductCard(
      image: products[index].image,
      title: products[index].name,
      price: products[index].price,
    ),
  ),
)

News Article

SkeletonizerPlus(
  enabled: isLoading,
  child: Column(
    children: [
      Image.network(article.imageUrl),
      Padding(
        padding: EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(article.title, style: TextStyle(fontSize: 24)),
            SizedBox(height: 8),
            Text(article.author),
            SizedBox(height: 16),
            Text(article.content),
          ],
        ),
      ),
    ],
  ),
)

๐Ÿ› ๏ธ API Reference

SkeletonizerPlus

Main widget that wraps a child and displays skeleton loading state.

Constructors

  • SkeletonizerPlus() - Automatic skeleton generation from child widget
  • SkeletonizerPlus.custom() - Custom bone layout
  • SkeletonizerPlus.withConfig() - Full animation configuration

Parameters

Parameter Type Default Description
enabled bool true Whether to show skeleton
child Widget? null Child widget to generate skeleton from
bones List<Bone>? null Custom bone layout (for .custom() constructor)
baseColor Color? Theme-based Base color of skeleton
highlightColor Color? Theme-based Highlight color of shimmer
speed Duration 1200ms Animation speed
direction ShimmerDirection ltr Shimmer direction
loop bool true Whether to loop infinitely
loopCount int? null Number of loops if loop is false
clipToBounds bool true Clip skeleton to bounds
optimizeForPerformance bool false Enable performance optimizations
theme ThemeData? null Theme override

Bone Types

BoneText

Mimics text with multiple words and lines.

BoneText(
  words: 3,        // Number of words per line
  lines: 2,        // Number of lines
  wordSpacing: 8.0,
  lineHeight: 16.0,
  lineSpacing: 4.0,
  radius: 4.0,     // Border radius
)

BoneCircle

Renders as a circle.

BoneCircle(
  radius: 24.0,    // Radius of the circle
)

BoneRect

Renders as a rectangle.

BoneRect(
  width: 100.0,
  height: 50.0,
  radius: 8.0,     // Border radius
)

BoneIcon

Mimics an icon (typically square with rounded corners).

BoneIcon(
  size: 24.0,      // Size (both width and height)
  radius: 4.0,     // Border radius
)

AnimationConfig

Full animation configuration.

AnimationConfig(
  speed: Duration(milliseconds: 1200),
  baseColor: Colors.grey[300],
  highlightColor: Colors.grey[100],
  direction: ShimmerDirection.ltr,
  loop: true,
  loopCount: null,
)

ShimmerDirection

  • ShimmerDirection.ltr - Left to right
  • ShimmerDirection.rtl - Right to left
  • ShimmerDirection.topDown - Top to bottom
  • ShimmerDirection.bottomUp - Bottom to top

For detailed API documentation, see API_REFERENCE.md.

โšก Performance Tips

  1. Enable Performance Optimizations

    SkeletonizerPlus(
      enabled: isLoading,
      optimizeForPerformance: true,
      clipToBounds: true,
      child: YourWidget(),
    )
    
  2. Use for Large Lists

    • The package automatically optimizes for viewport visibility
    • Only visible bones are animated when possible
  3. Consider RepaintBoundary

    • For complex widget trees, wrap with RepaintBoundary for additional optimization

๐ŸŒ“ Theme Integration

The package automatically adapts to your app's theme:

MaterialApp(
  theme: ThemeData.light(),
  darkTheme: ThemeData.dark(),
  themeMode: ThemeMode.system,
  // SkeletonizerPlus automatically uses appropriate colors
  home: MyApp(),
)

Light Theme: Uses Colors.grey[300] as base, Colors.grey[100] as highlight
Dark Theme: Uses Colors.grey[800] as base, Colors.grey[700] as highlight

You can override these defaults:

SkeletonizerPlus(
  enabled: isLoading,
  baseColor: Colors.blue[200],
  highlightColor: Colors.blue[50],
  child: YourWidget(),
)

๐Ÿงช Testing

Run tests with:

flutter test

The package includes comprehensive widget tests for:

  • Skeleton appearance/disappearance
  • Custom bone layouts
  • Theme integration
  • Animation configuration
  • Sliver support

๐Ÿ› Troubleshooting

Skeleton Not Appearing

  • โœ… Ensure enabled is true
  • โœ… Verify child widget is not null
  • โœ… Check that bones are being generated (use custom bones for debugging)

Performance Issues

  • โœ… Enable optimizeForPerformance: true
  • โœ… Set clipToBounds: true
  • โœ… Consider reducing animation speed for large lists

Colors Not Adapting to Theme

  • โœ… Ensure Theme.of(context) is available
  • โœ… Or provide explicit theme parameter
  • โœ… Check that baseColor and highlightColor are not overriding theme

Sliver Not Working

  • โœ… Use SliverSkeletonizerPlus instead of SkeletonizerPlus
  • โœ… Ensure it's inside a CustomScrollView
  • โœ… Check that child is a valid sliver widget

๐Ÿ“ฑ Platform Support

Platform Support
Android โœ… Full support
iOS โœ… Full support
Web โœ… Full support
macOS โœ… Full support
Windows โœ… Full support
Linux โœ… Full support

๐Ÿ‘จโ€๐Ÿ’ป Author

Godfrey Lebo - Fullstack Developer & Technical PM

With 9+ years of industry experience, I specialize in building AI-powered applications, scalable mobile solutions, and secure backend systems. I've led teams delivering marketplaces, fintech platforms, and AI applications serving thousands of users.

๐Ÿค Contributing

We welcome contributions! Whether you're fixing bugs, adding features, or improving documentation, your help makes this package better for everyone.

Ways to contribute:

  • ๐Ÿ› Report bugs
  • ๐Ÿ’ก Suggest new features
  • ๐Ÿ“ Improve documentation
  • ๐Ÿ”ง Submit pull requests

๐Ÿ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

๐Ÿ“š Additional Resources

๐Ÿ™ Acknowledgments

  • Flutter team for the amazing framework
  • Community contributors and users
  • Inspiration from various skeleton loading implementations

Made with โค๏ธ by Godfrey Lebo

If this package helps improve your app's loading experience, consider giving it a โญ on GitHub!

Libraries

skeletonizer_plus
A production-quality Flutter package for automatic skeleton loading states with shimmer animations, theme support, and performance optimizations.