🎨 Adaptive Shimmer

The ultimate skeleton loader for Flutter. Zero dependencies, maximum power.

Pub Version License: MIT

Why Choose This? β€’ Get Started β€’ Examples β€’ Learn More


πŸš€ Why Choose Adaptive Shimmer?

Feature Details
Zero Dependencies Pure Flutter, no external packages
One Line of Code Wrap any widget, get instant skeleton loading
Smart Auto-Detection Automatically transforms your widgets to skeletons
8 Directions LTR, RTL, TTB, BTB, Diagonal, Wave, and more
Complete Control Pause, resume, stop animations with ShimmerController
Beautiful Themes 8 built-in presets + unlimited custom options
Accessibility First Respects system motion preferences automatically
Advanced Features Custom transformers, nested skeletons, memoization
Production Ready Enterprise-grade Flutter apps

πŸ“¦ Installation

flutter pub add adaptive_shimmer

Or add to pubspec.yaml:

dependencies:
  adaptive_shimmer: ^1.2.0

⚑ Code Examples

1️⃣ Basic Loading (One Line!)

import 'package:adaptive_shimmer/adaptive_shimmer.dart';

AdaptiveShimmer(
  loading: isLoading,
  child: MyContentWidget(),
)

That's it! Shimmer applied, automatic on/off.


2️⃣ Auto-Transform with SmartSkeleton

No need for separate skeleton widgets!

SmartSkeleton(
  loading: isLoading,
  child: Column(
    children: [
      Text('Product Name'),
      Image.network(productUrl),
      Text('Price: $99.99'),
    ],
  ),
)

Automatically converts:

  • Text() β†’ Skeleton lines
  • Image() β†’ Skeleton boxes
  • Respects shapes & borders

3️⃣ ListView/GridView Skeletons

Perfect for dynamic lists:

SmartCollectionSkeleton(
  loading: isLoading,
  type: CollectionType.list,  // or .grid
  skeletonConfig: CollectionSkeletonConfig(
    itemCount: 5,
    itemHeight: 120,
  ),
  child: MyListView(),
)

4️⃣ Animation Control

final controller = ShimmerController();

AdaptiveShimmer(
  loading: true,
  controller: controller,
  child: MyWidget(),
)

controller.pause();    // Pause
controller.resume();   // Resume
controller.stop();     // Stop
controller.toggle();   // Toggle

5️⃣ Themes (8 Built-in)

AdaptiveShimmer.withTheme(
  loading: isLoading,
  theme: ShimmerTheme.dark,  // light, fast, slow, subtle, prominent
  child: MyWidget(),
)

Or custom:

theme: ShimmerTheme.custom(
  baseColor: Colors.grey[300],
  highlightColor: Colors.white,
  duration: Duration(milliseconds: 1200),
  intensity: 0.6,
)

6️⃣ Staggered Effect

StaggeredShimmer(
  children: [
    SkeletonBox(width: 300, height: 100),
    SizedBox(height: 16),
    SkeletonLine(width: 250),
    SizedBox(height: 8),
    SkeletonLine(width: 200),
  ],
  staggerDuration: Duration(milliseconds: 200),
)

🎨 Animation Types

AnimationType.shimmer,    // Wave effect (default)
AnimationType.pulse,      // Fade in/out
AnimationType.combined,   // Both effects

🧭 8 Directions

ShimmerDirection.ltr,            // Left to Right
ShimmerDirection.rtl,            // Right to Left
ShimmerDirection.ttb,            // Top to Bottom
ShimmerDirection.btt,            // Bottom to Top
ShimmerDirection.diagonalLTR,    // Diagonal β†˜
ShimmerDirection.diagonalRTL,    // Diagonal ↙
ShimmerDirection.diagonalBLTR,   // Diagonal β†—
ShimmerDirection.wave,           // Wave pattern

βš™οΈ Smart Configuration Strategies

Clean, semantic API using enums:

SmartSkeletonConfig(
  // What to replace?
  replacementStrategy: SkeletonReplacementStrategy.textAndImages,
  
  // Fill empty space?
  fillingStrategy: FillingStrategy.spaceOnly,
  
  // Cache performance?
  cacheStrategy: CacheStrategy.enabled,
  
  // Allow nesting?
  nestingStrategy: NestingStrategy.limited,
)

πŸ”§ Advanced Features

Nested Skeletons

SmartSkeleton(
  loading: outerLoading,
  child: SmartSkeleton(
    loading: innerLoading,
    child: InnerWidget(),
  ),
)

Performance Optimization

SmartSkeletonConfig(
  cacheStrategy: CacheStrategy.aggressive,
)

final stats = SmartSkeleton.getCacheStats();
SmartSkeleton.clearCache();

Testing Utilities

import 'package:adaptive_shimmer/testing_utils.dart';

ShimmerTester.findSkeletonWidgets(context);
ShimmerTester.countSkeletonsByType(context);
ShimmerTester.verifySkeletonCount(context, expected: 5);

Custom Transformers

SmartSkeleton(
  loading: isLoading,
  config: SmartSkeletonConfig(
    customTransformers: [
      SkeletonTransformer(
        predicate: (w) => w is MyCustomWidget,
        transformer: (w) => SkeletonBox(width: 200, height: 100),
        priority: 10,
      ),
    ],
  ),
  child: YourWidget(),
)

πŸ“¦ Pre-built Components

SkeletonBox(width: 100, height: 100)        // Rectangle
SkeletonCircle(radius: 40)                  // Circle
SkeletonLine(width: 200, height: 12)        // Text line
SkeletonParagraph(width: double.infinity)   // Multi-line

ScreenShimmer(...)                          // Full-page loading
ShimmerTransition(...)                      // Smooth fade-in
StaggeredShimmer(...)                       // Cascade effect
CollectionSkeleton(...)                     // List/grid skeletons

πŸ’‘ Best Practices

βœ… Use SmartSkeleton for auto-detection
βœ… Set realistic itemCount for collections
βœ… Theme consistently with presets
βœ… Motion preferences are automatic
βœ… Cache for high-frequency transforms
βœ… Test with testing utilities


🎯 Use Cases

βœ“ E-commerce products
βœ“ Social media feeds
βœ“ Search results
βœ“ User profiles
βœ“ News articles
βœ“ Chat messages
βœ“ Data tables
βœ“ Dashboards


⚑ Performance

  • GPU-accelerated animations (ShaderMask)
  • Built-in transformation caching
  • Zero re-renders on rebuilds
  • ~10KB package size (no dependencies)

πŸ“– Real-World Examples

E-commerce Product List

ScreenShimmer(
  loading: isLoadingProducts,
  child: ListView.builder(
    itemCount: products.length,
    itemBuilder: (_, i) => ProductCard(product: products[i]),
  ),
)

Social Media Feed

StaggeredShimmer(
  children: List.generate(3, (_) => ShimmerBox(width: double.infinity, height: 300)),
  staggerDuration: Duration(milliseconds: 150),
)

User Profile

ShimmerTransition(
  loading: isLoadingProfile,
  loadingChild: SkeletonProfilePage(),
  child: ProfilePage(user: user),
)

πŸ› Troubleshooting

Shimmer appears too bright/dim

Adjust the intensity parameter (0.0 - 1.0).

Animation is too fast/slow

Modify the duration parameter.

Widget not shimmering on ScreenShimmer

Ensure it's not wrapped with ShimmerExclude.


πŸ“ License

MIT License - See LICENSE file for details


🀝 Contributing

Found a bug or have a feature idea? Contributions are welcome!


πŸ’¬ Support & Feedback

Love this package? Please help:


Built with ❀️ by Abhijith )


#### Circle Skeleton
```dart
SkeletonCircle(
  radius: 40,
)

Line Skeleton (for text)

SkeletonLine(
  width: 150,
  height: 10,
)

Screen-Wide Shimmer

Wrap your entire screen to apply shimmer to all components:

ScreenShimmer(
  loading: isLoading,
  child: Scaffold(
    appBar: AppBar(title: Text('My App')),
    body: SingleChildScrollView(
      child: Column(
        children: [
          // All widgets inside will shimmer during loading
          Text('Content'),
          Image.network('...'),
          // ... more widgets
        ],
      ),
    ),
  ),
)

Excluding Widgets from Screen Shimmer

Use ShimmerExclude to keep certain widgets visible during screen shimmer:

ScreenShimmer(
  loading: isLoading,
  child: Scaffold(
    appBar: AppBar(title: Text('My App')),
    body: Column(
      children: [
        // This will shimmer
        ShimmerBox(width: 200, height: 100),
        
        // This will NOT shimmer - visible during loading
        ShimmerExclude(
          child: ElevatedButton(
            onPressed: () {},
            child: Text('Retry'),
          ),
        ),
        
        // This will shimmer
        ShimmerLine(width: 300),
      ],
    ),
  ),
)

Animation Types

Shimmer (Default)

Classic left-to-right shimmer wave effect.

AdaptiveShimmer(
  loading: true,
  animationType: AnimationType.shimmer,
  child: MyWidget(),
)

Pulse

Fading in and out effect.

AdaptiveShimmer(
  loading: true,
  animationType: AnimationType.pulse,
  child: MyWidget(),
)

Combined

Shimmer + pulse effect for enhanced visual feedback.

AdaptiveShimmer(
  loading: true,
  animationType: AnimationType.combined,
  child: MyWidget(),
)

Customization

Custom Colors

AdaptiveShimmer(
  loading: true,
  baseColor: Color(0xFFE0E0E0),
  highlightColor: Color(0xFFF5F5F5),
  child: MyWidget(),
)

Custom Animation Duration

AdaptiveShimmer(
  loading: true,
  duration: Duration(milliseconds: 1000),
  child: MyWidget(),
)

Disable Animation

AdaptiveShimmer(
  loading: true,
  enabled: false,
  child: MyWidget(),
)

Advanced Example: Product Card

Container(
  padding: EdgeInsets.all(12),
  child: Row(
    children: [
      SkeletonCircle(radius: 40),
      SizedBox(width: 12),
      Expanded(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            SkeletonLine(width: 150, height: 12),
            SizedBox(height: 8),
            SkeletonParagraph(
              width: double.infinity,
              lineCount: 2,
              lineHeight: 10,
            ),
          ],
        ),
      ),
    ],
  ),
)

πŸ“„ License

MIT License - feel free to use in commercial projects


🀝 Contributing

Found a bug or have a feature idea? Contributions welcome!


Made with ❀️ for the Flutter community

Pub.dev β€’ GitHub

Libraries

adaptive_shimmer