CINXE.COM
skeletonizer | Flutter package
<!DOCTYPE html> <html lang="en-us"><head><script src="https://www.googletagmanager.com/gtm.js?id=GTM-MX6DBN9" async="async"></script><script src="/static/hash-o6oemknr/js/gtm.js" async="async"></script><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="ie=edge"/><meta name="viewport" content="width=device-width, initial-scale=1"/><meta name="twitter:card" content="summary"/><meta name="twitter:site" content="@dart_lang"/><meta name="twitter:description" content="Converts already built widgets into skeleton loaders with no extra effort."/><meta name="twitter:image" content="https://pub.dev/static/hash-o6oemknr/img/pub-dev-icon-cover-image.png"/><meta property="og:type" content="website"/><meta property="og:site_name" content="Dart packages"/><meta property="og:title" content="skeletonizer | Flutter package"/><meta property="og:description" content="Converts already built widgets into skeleton loaders with no extra effort."/><meta property="og:image" content="https://pub.dev/static/hash-o6oemknr/img/pub-dev-icon-cover-image.png"/><meta property="og:url" content="https://pub.dev/packages/skeletonizer"/><title>skeletonizer | Flutter package</title><link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Google+Sans:wght@400;500;700&family=Google+Sans+Display:wght@400&family=Google+Sans+Text:wght@400;500;700&family=Google+Sans+Mono:wght@400;700&display=swap"/><link rel="shortcut icon" href="/static/hash-o6oemknr/img/flutter-logo-32x32.png"/><link rel="stylesheet" href="https://www.gstatic.com/glue/v25_0/ccb.min.css"/><link rel="search" type="application/opensearchdescription+xml" title="Dart packages" href="/osd.xml"/><link rel="canonical" href="https://pub.dev/packages/skeletonizer"/><meta name="description" content="Converts already built widgets into skeleton loaders with no extra effort."/><link rel="alternate" type="application/atom+xml" title="Updated Packages Feed for Pub" href="/feed.atom"/><link rel="stylesheet" type="text/css" href="/static/hash-o6oemknr/material/bundle/styles.css"/><link rel="stylesheet" type="text/css" href="/static/hash-o6oemknr/css/style.css"/><script src="/static/hash-o6oemknr/material/bundle/script.min.js" defer="defer"></script><script src="/static/hash-o6oemknr/js/script.dart.js" defer="defer"></script><script src="https://www.gstatic.com/brandstudio/kato/cookie_choice_component/cookie_consent_bar.v3.js" defer="defer" data-autoload-cookie-consent-bar="true"></script><meta name="pub-page-data" content="eyJwa2dEYXRhIjp7InBhY2thZ2UiOiJza2VsZXRvbml6ZXIiLCJ2ZXJzaW9uIjoiMS40LjIiLCJsaWtlcyI6MTU0NCwicHVibGlzaGVySWQiOiJjb2RlbmVzcy5seSIsImlzRGlzY29udGludWVkIjpmYWxzZSwiaXNMYXRlc3QiOnRydWV9LCJzZXNzaW9uQXdhcmUiOmZhbHNlfQ=="/><link rel="preload" href="/static/hash-o6oemknr/highlight/highlight-with-init.js" as="script"/></head><body class="light-theme"><script src="/static/hash-o6oemknr/js/dark-init.js"></script><noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-MX6DBN9" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript><div class="site-header"><button class="hamburger" aria-label="menu toggle"></button><a class="logo" href="/"><img class="site-logo" src="/static/hash-o6oemknr/img/pub-dev-logo.svg" alt="" width="140" height="30" role="presentation"/></a><div class="site-header-space"></div><div class="site-header-mask"></div><div class="site-header-search"><form action="/packages" method="GET"><input class="site-header-search-input" name="q" placeholder="New search..." autocomplete="on" title="Search"/></form></div><nav class="site-header-nav scroll-container"><div class="nav-login-container"><button id="-account-login" class="nav-main-button link">Sign in</button></div><div class="nav-container nav-help-container hoverable"><button class="nav-main-button">Help</button><div class="nav-hover-popup"><div class="nav-table-columns"><div class="nav-table-column"><h3>Pub.dev</h3><a class="nav-link" href="/help/search" rel="noopener" target="_blank">Searching for packages</a><a class="nav-link" href="/help/scoring" rel="noopener" target="_blank">Package scoring and pub points</a></div><div class="nav-table-column"><h3>Flutter</h3><a class="nav-link" href="https://flutter.dev/using-packages/" rel="noopener" target="_blank">Using packages</a><a class="nav-link" href="https://flutter.dev/developing-packages/" rel="noopener" target="_blank">Developing packages and plugins</a><a class="nav-link" href="https://dart.dev/tools/pub/publishing" rel="noopener" target="_blank">Publishing a package</a></div><div class="nav-table-column"><h3>Dart</h3><a class="nav-link" href="https://dart.dev/guides/packages" rel="noopener" target="_blank">Using packages</a><a class="nav-link" href="https://dart.dev/tools/pub/publishing" rel="noopener" target="_blank">Publishing a package</a></div></div></div></div><div class="nav-container nav-help-container-mobile foldable"><h3 class="foldable-button">Pub.dev <img class="foldable-icon" src="/static/hash-o6oemknr/img/nav-mobile-foldable-icon.svg" alt="toggle folding of the section" width="13" height="6"/></h3><div class="foldable-content"><a class="nav-link" href="/help/search" rel="noopener" target="_blank">Searching for packages</a><a class="nav-link" href="/help/scoring" rel="noopener" target="_blank">Package scoring and pub points</a></div></div><div class="nav-container nav-help-container-mobile foldable"><h3 class="foldable-button">Flutter <img class="foldable-icon" src="/static/hash-o6oemknr/img/nav-mobile-foldable-icon.svg" alt="toggle folding of the section" width="13" height="6"/></h3><div class="foldable-content"><a class="nav-link" href="https://flutter.dev/using-packages/" rel="noopener" target="_blank">Using packages</a><a class="nav-link" href="https://flutter.dev/developing-packages/" rel="noopener" target="_blank">Developing packages and plugins</a><a class="nav-link" href="https://dart.dev/tools/pub/publishing" rel="noopener" target="_blank">Publishing a package</a></div></div><div class="nav-container nav-help-container-mobile foldable"><h3 class="foldable-button">Dart <img class="foldable-icon" src="/static/hash-o6oemknr/img/nav-mobile-foldable-icon.svg" alt="toggle folding of the section" width="13" height="6"/></h3><div class="foldable-content"><a class="nav-link" href="https://dart.dev/guides/packages" rel="noopener" target="_blank">Using packages</a><a class="nav-link" href="https://dart.dev/tools/pub/publishing" rel="noopener" target="_blank">Publishing a package</a></div></div></nav></div><div id="banner-container"></div><main class="container"><div class="detail-wrapper -active -has-info-box"><div class="detail-header -is-loose"><div class="detail-container"><div class="detail-header-outer-block"><div class="detail-header-content-block"><h1 class="title">skeletonizer 1.4.2 <span class="pkg-page-title-copy"><img class="pkg-page-title-copy-icon filter-invert-on-dark" src="/static/hash-o6oemknr/img/content-copy-icon.svg" alt="copy "skeletonizer: ^1.4.2" to clipboard" width="18" height="18" title="Copy "skeletonizer: ^1.4.2" to clipboard" data-copy-content="skeletonizer: ^1.4.2" data-ga-click-event="copy-package-version"/><div class="pkg-page-title-copy-feedback"><span class="code">skeletonizer: ^1.4.2</span> copied to clipboard</div></span></h1><div class="metadata">Published <span><a class="-x-ago" href="" title="Jul 31, 2024" aria-label="4 months ago" aria-role="button" role="button" data-timestamp="1722449651390">4 months ago</a></span> • <a class="-pub-publisher" href="/publishers/codeness.ly"><img class="-pub-publisher-shield filter-invert-on-dark" src="/static/hash-o6oemknr/img/material-icon-verified.svg" alt="verified publisher" width="14" height="14" title="Published by a pub.dev verified publisher"/>codeness.ly</a><span class="package-badge" title="Package is compatible with Dart 3.">Dart 3 compatible</span></div><div class="detail-tags-and-like"><div class="detail-tags"><div class="-pub-tag-badge"><span class="tag-badge-main">SDK</span><a class="tag-badge-sub" href="/packages?q=sdk%3Aflutter" rel="nofollow" title="Packages compatible with Flutter SDK">Flutter</a></div><div class="-pub-tag-badge"><span class="tag-badge-main">Platform</span><a class="tag-badge-sub" href="/packages?q=platform%3Aandroid" rel="nofollow" title="Packages compatible with Android platform">Android</a><a class="tag-badge-sub" href="/packages?q=platform%3Aios" rel="nofollow" title="Packages compatible with iOS platform">iOS</a><a class="tag-badge-sub" href="/packages?q=platform%3Alinux" rel="nofollow" title="Packages compatible with Linux platform">Linux</a><a class="tag-badge-sub" href="/packages?q=platform%3Amacos" rel="nofollow" title="Packages compatible with macOS platform">macOS</a><a class="tag-badge-sub" href="/packages?q=platform%3Aweb" rel="nofollow" title="Packages compatible with Web platform">web</a><a class="tag-badge-sub" href="/packages?q=platform%3Awindows" rel="nofollow" title="Packages compatible with Windows platform">Windows</a></div></div><div class="detail-like"><button id="-pub-like-icon-button" class="mdc-icon-button" data-ga-click-event="toggle-like" aria-pressed="false" title="Like this package"><img class="mdc-icon-button__icon" src="/static/hash-o6oemknr/img/like-inactive.svg" alt="liked status: inactive" width="18" height="18"/><img class="mdc-icon-button__icon mdc-icon-button__icon--on" src="/static/hash-o6oemknr/img/like-active.svg" alt="liked status: active" width="18" height="18"/></button><span class="likes-count"><span id="likes-count">1.5k</span></span></div></div></div></div></div></div><div class="detail-container"><div class="detail-lead"><div class="detail-metadata-toggle"><div class="detail-metadata-toggle-icon">→</div><h3 class="detail-lead-title">Metadata</h3></div><p class="detail-lead-text">Converts already built widgets into skeleton loaders with no extra effort.</p><p class="detail-lead-more"><a class="detail-metadata-toggle">More...</a></p></div></div><div class="detail-body"><div class="detail-tabs"><div class="detail-tabs-wide-header"><div class="detail-container"><ul class="detail-tabs-header"><li class="detail-tab tab-button detail-tab-readme-title -active">Readme</li><li class="detail-tab tab-link detail-tab-changelog-title"><a href="/packages/skeletonizer/changelog" role="button">Changelog</a></li><li class="detail-tab tab-link detail-tab-example-title"><a href="/packages/skeletonizer/example" role="button">Example</a></li><li class="detail-tab tab-link detail-tab-installing-title"><a href="/packages/skeletonizer/install" role="button">Installing</a></li><li class="detail-tab tab-link detail-tab-versions-title"><a href="/packages/skeletonizer/versions" role="button">Versions</a></li><li class="detail-tab tab-link detail-tab-analysis-title"><a href="/packages/skeletonizer/score" role="button">Scores</a></li></ul></div></div><div class="detail-container detail-body-main"><div class="detail-tabs-content"><section class="tab-content detail-tab-readme-content -active markdown-body"><br> <p align="center"> <img src="https://raw.githubusercontent.com/Milad-Akarie/skeletonizer/main/art/skeletonizer_logo.svg" height="130" alt="skeletonizer logo"> </p> <p align="center"> <a href="https://img.shields.io/badge/License-MIT-green" rel="ugc"><img src="https://img.shields.io/badge/License-MIT-green" alt="MIT License"></a> <a href="https://github.com/Milad-Akarie/skeletonizer/stargazers" rel="ugc"><img src="https://img.shields.io/github/stars/Milad-Akarie/skeletonizer?style=flat&logo=github&colorB=green&label=stars" alt="stars"></a> <a href="https://pub.dev/packages/skeletonizer"><img src="https://img.shields.io/pub/v/skeletonizer.svg?label=pub&color=orange" alt="pub version"></a> </p> <p align="center"> <a href="https://www.buymeacoffee.com/miladakarie" target="_blank" rel="ugc"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" height="30px" width="108px"></a> </p> <hr> <ul> <li><a href="#introduction">Introduction</a></li> <li><a href="#basic-usage">Basic usage</a></li> <li><a href="#the-need-for-fake-data">The need for fake data</a></li> <li><a href="#annotations">Annotations</a></li> <li><a href="#creating-skeletons-manually">Creating Skeletons manually</a></li> <li><a href="#customization">Customization</a></li> <li><a href="#resources">Resources</a></li> </ul> <h2 class="hash-header" id="introduction">Introduction <a href="#introduction" class="hash-link">#</a></h2> <h3 class="hash-header" id="what-are-skeleton-loaders">What are skeleton loaders? <a href="#what-are-skeleton-loaders" class="hash-link">#</a></h3> <p>UI skeleton loading is a technique used to enhance user experience during web or app loading. It involves displaying a simplified, static version of the user interface while the actual content is being fetched. This placeholder UI gives the illusion of instant loading and prevents users from perceiving long loading times.</p> <h3 class="hash-header" id="motivation">Motivation <a href="#motivation" class="hash-link">#</a></h3> <p>Creating a skeleton-layout for your screens doesn't only feel like a duplicate work but things can go out of sync real quick, when updating the actual layout we often forget to update the corresponding skeleton-layout.</p> <h3 class="hash-header" id="how-does-it-work">How does it work? <a href="#how-does-it-work" class="hash-link">#</a></h3> <p>As the name suggests, skeletonizer will reduce your already existing layouts into mere skeletons and apply painting effects on them, typically a shimmer effect. It automatically does the job for you, in addition skeleton annotations can be used to change how specific widgets are skeletonized.</p> <h2 class="hash-header" id="basic-usage">Basic usage <a href="#basic-usage" class="hash-link">#</a></h2> <p>Simply wrap your layout with <code>Skeletonizer</code> widget or <code>SliverSkeletonizer</code> | <code>Skeletonizer.sliver</code> for sliver widgets.</p> <pre><code class="language-dart"> Skeletonizer( enabled: _loading, child: ListView.builder( itemCount: 7, itemBuilder: (context, index) { return Card( child: ListTile( title: Text('Item number $index as title'), subtitle: const Text('Subtitle here'), trailing: const Icon(Icons.ac_unit), ), ); }, ), ) </code></pre> <h4 id="skeletonizer-with-default-config">Skeletonizer with default config</h4> <p><strong>Note: all the following shimmer effects are disturbed by the gif optimization</strong></p> <p><a href="https://github.com/Milad-Akarie/skeletonizer/blob/main/art/skeletonizer_demo_video.mp4?raw=true" rel="ugc">Click here for HD video demo</a></p> <p><img src="https://github.com/Milad-Akarie/skeletonizer/blob/main/art/skeletonizer_demo_1.gif?raw=true" alt=""></p> <h4 id="skeletonizer-with-no-containers">Skeletonizer with no containers</h4> <pre><code class="language-dart"> Skeletonizer(ignoreContainers: true) </code></pre> <p><img src="https://github.com/Milad-Akarie/skeletonizer/blob/main/art/skeletonizer_demo_2.gif?raw=true" alt=""></p> <h2 class="hash-header" id="the-need-for-fake-data">The need for fake data <a href="#the-need-for-fake-data" class="hash-link">#</a></h2> <p>In order for skeletonizer to work it actually needs a layout, but in most cases the layout would need data to shape, e.g the following ListView ill not render anything unless <code>users</code> is populated, because if users is empty we have no layout which means we have nothing to skeletonize.</p> <pre><code class="language-dart">Skeletonizer( enabled: _loading, child: ListView.builder( itemCount: users.length, itemBuilder: (context, index) { return Card( child: ListTile( title: Text(users[index].name), subtitle: Text(users[index].jobTitle), leading: CircleAvatar( radius: 24, backgroundImage: NetworkImage(users[index].avatar), ), ), ); }, ), ) </code></pre> <p>So the key here is to provide fake data for the layout to shape until the real data is fetched form the server, and we would have such a setup in our build method:</p> <pre><code class="language-dart"> if (_loading) { final fakeUsers = List.filled(7, User( name: 'User name', jobTitle: 'Developer', avatar: '' ), ); return Skeletonizer( child: UserList(users: fakeUsers), ); } else { return UserList(users: realUsers); } </code></pre> <p>or by utilizing the <code>enabled</code> flag</p> <pre><code class="language-dart"> { final users = _loading ? List.filled( 7, const User( name: 'User name', jobTitle: 'Developer', avatar: '' ) : realUsers; ); return Skeletonizer( enabled: _loading, child: UserList(users: users), ); </code></pre> <p><strong>Note</strong>: you can use BoneMock to easily generate fake text for your mock data</p> <pre><code class="language-dart"> final fakeUsers = List.filled(7, User( name: BoneMock.name, jobTitle: BoneMock.words(2), email: BoneMock.email, createdAt: BoneMock.date, ), ); </code></pre> <p>Now we have our layout but one issue remains, if you run the above example you'll get an error in your console stating that an invalid url was passed to <code>NetworkImage</code> which is legit because our fake avatar url is an empty string, in such cases we need to make sure NetworkImage is not in our widget tree when skeletonizer is enabled and we do that by using a skeleton annotation called <code>Skeleton.replace</code> ..read more about annotations below.</p> <pre><code class="language-dart">Skeletonizer( enabled: _loading, child: ListView.builder( itemCount: users.length, itemBuilder: (context, index) { return Card( child: ListTile( title: Text(users[index].name), subtitle: Text(users[index].jobTitle), leading: Skeleton.replace( width: 48, // width of replacement height: 48, // height of replacement child: CircleAvatar( radius: 24, backgroundImage: NetworkImage(users[index].avatar), ), ), ); }, ), ) </code></pre> <p>or you can do it directly like follows:</p> <pre><code class="language-dart">Skeletonizer( enabled: _loading, child: ListView.builder( itemCount: users.length, itemBuilder: (context, index) { return Card( child: ListTile( title: Text(users[index].name), subtitle: Text(users[index].jobTitle), leading: CircleAvatar( radius: 24, backgroundImage: _loading ? null : NetworkImage(users[index].avatar), ), ), ),); }, ), ) </code></pre> <p><strong>Note</strong>: you can also check wither a skeletonizer is enabled inside descendent widgets using:</p> <pre><code class="language-dart">Skeletonizer.of(context).enabled; </code></pre> <h2 class="hash-header" id="annotations">Annotations <a href="#annotations" class="hash-link">#</a></h2> <p>We can use annotations to change how some widgets should be skeletonized, skeleton annotations have no effect on the real layout as they only hold information for skeletonizer to use when it's enabled.</p> <h3 class="hash-header" id="skeletonignore">Skeleton.ignore <a href="#skeletonignore" class="hash-link">#</a></h3> <p>Widgets annotated with <code>Skeleton.ignore</code> will not be skeletonized</p> <pre><code class="language-dart">Card( child: ListTile( title: Text('The title goes here'), subtitle: Text('Subtitle here'), trailing: Skeleton.ignore( // the icon will not be skeletonized child: Icon(Icons.ac_unit, size: 40), ), ), ) </code></pre> <p><img src="https://github.com/Milad-Akarie/skeletonizer/blob/main/art/ignored_skeleton_demo.gif?raw=true" alt=""></p> <h3 class="hash-header" id="skeletonleaf">Skeleton.leaf <a href="#skeletonleaf" class="hash-link">#</a></h3> <p>Widgets annotated with <code>Skeleton.leaf</code> marks containers as leafs, leafs are painted using the shader paint.</p> <pre><code class="language-dart">Skeleton.leaf( child : Card( child: ListTile( title: Text('The title goes here'), subtitle: Text('Subtitle here'), trailing: Icon(Icons.ac_unit, size: 40), ), ) ) </code></pre> <p><img src="https://github.com/Milad-Akarie/skeletonizer/blob/main/art/leaf_skeleton_demo.gif?raw=true" alt=""></p> <h3 class="hash-header" id="skeletonkeep">Skeleton.keep <a href="#skeletonkeep" class="hash-link">#</a></h3> <p>Widgets annotated with <code>Skeleton.keep</code> will not be skeletonized but will be painted as is</p> <pre><code class="language-dart">Card( child: ListTile( title: Text('The title goes here'), subtitle: Text('Subtitle here'), trailing: Skeleton.keep( // the icon will be painted as is child: Icon(Icons.ac_unit, size: 40), ), ), ) </code></pre> <p><img src="https://github.com/Milad-Akarie/skeletonizer/blob/main/art/kept_skeleton_demo.gif?raw=true" alt=""></p> <h3 class="hash-header" id="skeletonshade">Skeleton.shade <a href="#skeletonshade" class="hash-link">#</a></h3> <p>Widgets annotated with <code>Skeleton.shade</code> will not be skeletonized but will be shaded by a shader mask.</p> <p><strong>Note</strong>: <code>CustomPainter</code> widgets need to be explicitly annotated with <code>Skeleton.shade</code> to be shaded.</p> <pre><code class="language-dart">Card( child: ListTile( title: Text('The title goes here'), subtitle: Text('Subtitle here'), trailing: Skeleton.shade( // the icon will be shaded by shader mask child: Icon(Icons.ac_unit, size: 40), ), ), ) </code></pre> <p><img src="https://github.com/Milad-Akarie/skeletonizer/blob/main/art/shaded_skeleton_demo.gif?raw=true" alt=""></p> <h3 class="hash-header" id="skeletonreplace">Skeleton.replace <a href="#skeletonreplace" class="hash-link">#</a></h3> <p>Widgets annotated with <code>Skeleton.replace</code> will be replaced when skeletonizer is enabled and the replacement will be skeletonized, This is good for widgets that can not render with fake data like <code>Image.network()</code></p> <pre><code class="language-dart">Card( child: ListTile( title: Text('The title goes here'), subtitle: Text('Subtitle here'), trailing: Skeleton.replace( // the icon will be replaced when skeletonizer is enabled width: 50, // the width of the replacement height: 50, // the height of the replacement replacement: // defaults to a DecoratedBox child: Icon(Icons.ac_unit, size: 40), ), ) ,) </code></pre> <p><img src="https://github.com/Milad-Akarie/skeletonizer/blob/main/art/replaced_skeleton_demo.gif?raw=true" alt=""></p> <h3 class="hash-header" id="skeletonunite">Skeleton.unite <a href="#skeletonunite" class="hash-link">#</a></h3> <p>Widgets annotated with <code>Skeleton.unite</code> will not be united and drawn as one big bone, this is good for when you have multiple small bones close to each other and you want to present them as one bone.</p> <pre><code class="language-dart">Card( child: ListTile( title: Text('Item number 1 as title'), subtitle: Text('Subtitle here'), trailing: Skeleton.unite( child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.ac_unit, size: 32), SizedBox(width: 8), Icon(Icons.access_alarm, size: 32), ], ), ), ), ) , </code></pre> <p><img src="https://github.com/Milad-Akarie/skeletonizer/blob/main/art/united_skeleton_demo.gif?raw=true" alt=""></p> <h3 class="hash-header" id="skeletonignorepointers">Skeleton.ignorePointers <a href="#skeletonignorepointers" class="hash-link">#</a></h3> <p>Widgets annotated with <code>Skeleton.ignorePointers</code> will ignore pointer events when skeletonizer is enabled.</p> <h2 class="hash-header" id="creating-skeletons-manually">Creating Skeletons manually <a href="#creating-skeletons-manually" class="hash-link">#</a></h2> <p>Originally, Skeletonizer worked its magic by creating skeletons from real widgets. But hey, we get it – sometimes you want to do your own thing, have a different layout, or just skip the whole fake data scene. Now, you can speed things up big time by crafting custom skeletons from scratch using Bone widgets. Now, you might wonder, "What sets this apart from other shimmer libraries?" Simple – Bone widgets are your time-saving superheroes. They mimic everyday UI components you'd typically want to shimmer, such as icons, texts, and buttons and use their actual theme data to design border radius and sizing information.</p> <pre><code class="language-dart">Skeletonizer.zone( child: Card( child: ListTile( leading: Bone.circle(size: 48), title: Bone.text(words: 2), subtitle: Bone.text(), trailing: Bone.icon(), ), ), ); </code></pre> <p><img src="https://github.com/Milad-Akarie/skeletonizer/blob/main/art/bone_widgets_demo.png?raw=true" alt=""></p> <p>Obviously, you can create any bone shape using <code>Bone(width, height)</code> or use the helpers <code>Bone.circle(size)</code> and <code>Bone.square(size)</code>. The cool part here is using mimic bone types like <code>Bone.icon()</code>, which, you guessed it, reads icon sizing information from the inherited theme. As such, Bone.text reads font size and line height from the inherited theme if not provided in the constructor. By default, it mimics 3 words (word = 5 letters), but you can easily change that. For multiline, use <code>Bone.multiText(lines: 3)</code>.</p> <p>Additionally, there's also <code>Bone.button()</code> which mimics actual Material buttons and <code>Bone.iconButton()</code> to mimic icon buttons.</p> <p>When opting for the manual approach, only Bone widgets get the shimmer treatment – they're the ones that'll be shaded. This means you can wrap other colorable widgets like cards, containers ..etc, without worrying about them getting shaded. which results to a seamless and perfect shimmer effect!</p> <h2 class="hash-header" id="customization">Customization <a href="#customization" class="hash-link">#</a></h2> <h3 class="hash-header" id="loading-effects">Loading effects <a href="#loading-effects" class="hash-link">#</a></h3> <p>Skeletonizer has 3 different painting effects to choose from which can be customized to your liking.</p> <p><strong>Note: Loading effects are disturbed by Gif optimization, these look much better on flutter</strong></p> <p><img src="https://github.com/Milad-Akarie/skeletonizer/blob/main/art/loading_effects_demo.gif?raw=true" alt=""></p> <p>Effects are configurable, e.g you can change the base color, highlight color, direction, and duration of ShineEffect like so:</p> <pre><code class="language-dart">Skeletonizer( effect: const ShimmerEffect( baseColor: Colors.grey[300], highlightColor: Colors.grey[100], duration: Duration(seconds: 1), ), child: ... ) </code></pre> <h3 class="hash-header" id="animating-the-transition-between-skeleton-and-content-slivers-are-not-supported">Animating the transition between skeleton and content (Slivers are not supported) <a href="#animating-the-transition-between-skeleton-and-content-slivers-are-not-supported" class="hash-link">#</a></h3> <p>you can animate the transition between skeleton and content by setting <code>enableSwitchAnimation</code> to true, animation can be customized by providing a <code>SwitchAnimationConfig</code>.</p> <pre><code class="language-dart">SwitchAnimationConfig({ this.duration = const Duration(milliseconds: 300), this.switchInCurve = Curves.linear, this.switchOutCurve = Curves.linear, this.transitionBuilder = AnimatedSwitcher.defaultTransitionBuilder, this.reverseDuration, }); </code></pre> <h3 class="hash-header" id="text-skeleton-config">Text skeleton config <a href="#text-skeleton-config" class="hash-link">#</a></h3> <p>You can provide a global text config options to skeletonizer widgets like</p> <pre><code class="language-dart">Skeletonizer( justifyMultiLineText: false, textBoneBorderRadius: TextBoneBorderRadius.fromHeightFactor(.5), ... ) </code></pre> <p><img src="https://github.com/Milad-Akarie/skeletonizer/blob/main/art/text_config_demo.gif?raw=true" alt=""></p> <h3 class="hash-header" id="ignorecontainers">ignoreContainers <a href="#ignorecontainers" class="hash-link">#</a></h3> <p>if you want to ignore all containers and only skeletonize their children you can set <code>ignoreContainers</code> to true</p> <h3 class="hash-header" id="containerscolor">containersColor <a href="#containerscolor" class="hash-link">#</a></h3> <p>if provided, all containers will be painted with this color otherwise the actual color will be</p> <h3 class="hash-header" id="using-the-inheritable-config-data">Using the inheritable Config data <a href="#using-the-inheritable-config-data" class="hash-link">#</a></h3> <p>You can pass a <code>SkeletonizerConfigData</code> as a theme extension to provide default configurations to all skeletonizer widgets in your app.</p> <pre><code class="language-dart">MaterialApp( theme: ThemeData( extensions: const [ SkeletonizerConfigData(), // default constructor has light theme config ], ), darkTheme: ThemeData( brightness: Brightness.dark, extensions: const [ SkeletonizerConfigData.dark(), // dark theme config ], ), ... ) </code></pre> <p>or you can Use <code>SkeletonizerConfig</code> to provide inheritable config data to all descendant Skeletonizer widgets.</p> <pre><code class="language-dart">SkeletonizerConfig( data: SkeletonizerConfigData( effect: const ShimmerEffect(), justifyMultiLineText: true, textBorderRadius: TextBoneBorderRadius(..), ignoreContainers: false, ), ..... ) </code></pre> <h2 class="hash-header" id="resources">Resources <a href="#resources" class="hash-link">#</a></h2> <ul> <li><a href="https://medium.com/@milad-akarie/flutter-skeleton-loader-using-skeletonizer-13d410dc4ac7" rel="ugc">Flutter skeleton loader using skeletonizer</a></li> </ul> <h3 class="hash-header" id="support-skeletonizer">Support Skeletonizer <a href="#support-skeletonizer" class="hash-link">#</a></h3> <p>You can support skeletonizer by liking it on Pub and staring it on Github, sharing ideas on how we can enhance a certain functionality or by reporting any problems you encounter and of course buying a couple coffees will help speed up the development process.</p> </section></div></div></div><aside class="detail-info-box"><a class="packages-scores" href="/packages/skeletonizer/score"><div class="packages-score packages-score-like"><div class="packages-score-value -has-value"><span class="packages-score-value-number">1544</span><span class="packages-score-value-sign"></span></div><div class="packages-score-label">likes</div></div><div class="packages-score packages-score-health"><div class="packages-score-value -has-value"><span class="packages-score-value-number">160</span><span class="packages-score-value-sign"></span></div><div class="packages-score-label">pub points</div></div><div class="packages-score packages-score-popularity"><div class="packages-score-value -has-value"><span class="packages-score-value-number">99</span><span class="packages-score-value-sign">%</span></div><div class="packages-score-label">popularity</div></div></a><div class="detail-screenshot-thumbnail"><div class="thumbnail-container" data-thumbnail="/packages/skeletonizer/versions/1.4.2/gen-res/gen/skeletonizer_logo_no_text.webp" data-thumbnail-descriptions-json="["Example of skeletonizer in action."]" data-ga-click-event="screenshot-thumbnail-click"><img class="thumbnail-image" src="/packages/skeletonizer/versions/1.4.2/gen-res/gen/190x190/skeletonizer_logo_no_text.webp" alt="screenshot" title="View screenshots" tabindex="0"/></div><img class="collections-icon" src="/static/hash-o6oemknr/img/collections_white_24dp.svg" alt="" width="30" height="30" role="presentation"/></div><h3 class="title">Publisher</h3><p><a href="/publishers/codeness.ly"><img class="-pub-publisher-shield filter-invert-on-dark" src="/static/hash-o6oemknr/img/material-icon-verified.svg" alt="verified publisher" width="14" height="14" title="Published by a pub.dev verified publisher"/>codeness.ly</a></p><h3 class="title pkg-infobox-metadata">Metadata</h3><p>Converts already built widgets into skeleton loaders with no extra effort.</p><p><a class="link" href="https://github.com/Milad-Akarie/skeletonizer" rel="ugc">Repository (GitHub)</a><br/><a class="link" href="https://github.com/Milad-Akarie/skeletonizer/issues" rel="ugc">View/report issues</a><br/></p><h3 class="title">Topics</h3><p><a href="/packages?q=topic%3Askeleton" rel="nofollow">#skeleton</a> <a href="/packages?q=topic%3Ashimmer-loading" rel="nofollow">#shimmer-loading</a> <a href="/packages?q=topic%3Askeleton-loader" rel="nofollow">#skeleton-loader</a> <a href="/packages?q=topic%3Aloading" rel="nofollow">#loading</a></p><h3 class="title">Documentation</h3><p><a class="link" href="/documentation/skeletonizer/latest/">API reference</a><br/></p><h3 class="title">License</h3><p><img class="inline-icon-img filter-invert-on-dark" src="/static/hash-o6oemknr/img/material-icon-balance.svg" alt="" width="14" height="14" role="presentation"/>MIT (<a href="/packages/skeletonizer/license">license</a>)</p><h3 class="title">Dependencies</h3><p><a href="/packages/collection" title="^1.18.0">collection</a>, <a href="https://api.flutter.dev/">flutter</a></p><h3 class="title">More</h3><p><a href="/packages?q=dependency%3Askeletonizer" rel="nofollow">Packages that depend on skeletonizer</a></p></aside></div><script type="application/ld+json">{"@context":"http\u003a\u002f\u002fschema.org","@type":"SoftwareSourceCode","name":"skeletonizer","version":"1.4.2","description":"skeletonizer - Converts already built widgets into skeleton loaders with no extra effort.","url":"https\u003a\u002f\u002fpub.dev\u002fpackages\u002fskeletonizer","dateCreated":"2023-06-18T12\u003a47\u003a59.671105Z","dateModified":"2024-07-31T18\u003a14\u003a11.390117Z","programmingLanguage":"Dart","image":"https\u003a\u002f\u002fpub.dev\u002fstatic\u002fimg\u002fpub-dev-icon-cover-image.png","license":"https\u003a\u002f\u002fpub.dev\u002fpackages\u002fskeletonizer\u002flicense"}</script></div><div class="detail-metadata"><h3 class="detail-metadata-title"><span class="detail-metadata-toggle">←</span> Metadata</h3><div class="detail-info-box"><a class="packages-scores" href="/packages/skeletonizer/score"><div class="packages-score packages-score-like"><div class="packages-score-value -has-value"><span class="packages-score-value-number">1544</span><span class="packages-score-value-sign"></span></div><div class="packages-score-label">likes</div></div><div class="packages-score packages-score-health"><div class="packages-score-value -has-value"><span class="packages-score-value-number">160</span><span class="packages-score-value-sign"></span></div><div class="packages-score-label">pub points</div></div><div class="packages-score packages-score-popularity"><div class="packages-score-value -has-value"><span class="packages-score-value-number">99</span><span class="packages-score-value-sign">%</span></div><div class="packages-score-label">popularity</div></div></a><div class="detail-screenshot-thumbnail"><div class="thumbnail-container" data-thumbnail="/packages/skeletonizer/versions/1.4.2/gen-res/gen/skeletonizer_logo_no_text.webp" data-thumbnail-descriptions-json="["Example of skeletonizer in action."]" data-ga-click-event="screenshot-thumbnail-click"><img class="thumbnail-image" src="/packages/skeletonizer/versions/1.4.2/gen-res/gen/190x190/skeletonizer_logo_no_text.webp" alt="screenshot" title="View screenshots" tabindex="0"/></div><img class="collections-icon" src="/static/hash-o6oemknr/img/collections_white_24dp.svg" alt="" width="30" height="30" role="presentation"/></div><h3 class="title">Publisher</h3><p><a href="/publishers/codeness.ly"><img class="-pub-publisher-shield filter-invert-on-dark" src="/static/hash-o6oemknr/img/material-icon-verified.svg" alt="verified publisher" width="14" height="14" title="Published by a pub.dev verified publisher"/>codeness.ly</a></p><h3 class="title pkg-infobox-metadata">Metadata</h3><p>Converts already built widgets into skeleton loaders with no extra effort.</p><p><a class="link" href="https://github.com/Milad-Akarie/skeletonizer" rel="ugc">Repository (GitHub)</a><br/><a class="link" href="https://github.com/Milad-Akarie/skeletonizer/issues" rel="ugc">View/report issues</a><br/></p><h3 class="title">Topics</h3><p><a href="/packages?q=topic%3Askeleton" rel="nofollow">#skeleton</a> <a href="/packages?q=topic%3Ashimmer-loading" rel="nofollow">#shimmer-loading</a> <a href="/packages?q=topic%3Askeleton-loader" rel="nofollow">#skeleton-loader</a> <a href="/packages?q=topic%3Aloading" rel="nofollow">#loading</a></p><h3 class="title">Documentation</h3><p><a class="link" href="/documentation/skeletonizer/latest/">API reference</a><br/></p><h3 class="title">License</h3><p><img class="inline-icon-img filter-invert-on-dark" src="/static/hash-o6oemknr/img/material-icon-balance.svg" alt="" width="14" height="14" role="presentation"/>MIT (<a href="/packages/skeletonizer/license">license</a>)</p><h3 class="title">Dependencies</h3><p><a href="/packages/collection" title="^1.18.0">collection</a>, <a href="https://api.flutter.dev/">flutter</a></p><h3 class="title">More</h3><p><a href="/packages?q=dependency%3Askeletonizer" rel="nofollow">Packages that depend on skeletonizer</a></p></div><p class="detail-lead-back"><a class="detail-metadata-toggle">Back</a></p></div><div id="-screenshot-carousel" class="carousel"><fab id="-carousel-prev" class="mdc-fab carousel-prev carousel-nav" data-mdc-auto-init="MDCRipple" title="Previous" data-ga-click-event="screenshot-carousel-prev-click" tabindex="0"><div class="mdc-fab__ripple"></div><img class="mdc-fab__icon" src="/static/hash-o6oemknr/img/keyboard_arrow_left.svg" alt="previous" width="24" height="24" aria-hidden="true"/></fab><div id="-image-container" class="image-container"></div><fab id="-carousel-next" class="mdc-fab carousel-next carousel-nav" data-mdc-auto-init="MDCRipple" title="Next" data-ga-click-event="screenshot-carousel-next-click" tabindex="0"><div class="mdc-fab__ripple"></div><img class="mdc-fab__icon" src="/static/hash-o6oemknr/img/keyboard_arrow_right.svg" alt="next" width="24" height="24" aria-hidden="true"/></fab><p id="-screenshot-description" class="screenshot-description"></p></div></main><footer class="site-footer"><a class="link" href="https://dart.dev/">Dart language</a><a class="link sep" href="/report?subject=package%3Askeletonizer&url=https%3A%2F%2Fpub.dev%2Fpackages%2Fskeletonizer">Report package</a><a class="link sep" href="/policy">Policy</a><a class="link sep" href="https://www.google.com/intl/en/policies/terms/">Terms</a><a class="link sep" href="https://developers.google.com/terms/">API Terms</a><a class="link sep" href="/security">Security</a><a class="link sep" href="https://www.google.com/intl/en/policies/privacy/">Privacy</a><a class="link sep" href="/help">Help</a><a class="link icon sep" href="/feed.atom"><img class="inline-icon" src="/static/hash-o6oemknr/img/rss-feed-icon.svg" alt="RSS" width="20" height="20" title="RSS/atom feed"/></a><a class="link icon github_issue" href="https://github.com/dart-lang/pub-dev/issues/new"><img class="inline-icon" src="/static/hash-o6oemknr/img/bug-report-white-96px.png" alt="bug report" width="20" height="20" title="Report an issue with this site"/></a></footer><script src="/static/hash-o6oemknr/highlight/highlight-with-init.js" defer="defer"></script></body></html>