top of page
Search

Implementing Shimmer Effect in Flutter

  • Writer: Aarthi Krishnan
    Aarthi Krishnan
  • May 24, 2024
  • 5 min read

Updated: May 24, 2024


Shimmer Effect Flutter
Shimmer Effect Flutter

Shimmer Effect Flutter Introduction:


Flutter is a powerful framework for creating visually appealing and natively compiled applications for mobile, web, and desktop from a single codebase. One impressive feature that can be incorporated into your Flutter app is the shimmer effect Flutter. This effect serves as a placeholder for your content while it loads, improving the user experience by visually indicating that data is being fetched. In this detailed guide, we will develop a Flutter app that showcases how to implement the shimmer effect in Flutter App, accompanied by a thorough explanation of the code.




Table of Contents


  1. Introduction

  2. Setting Up Flutter

  3. Creating the Flutter App

  4. Adding Dependencies

  5. Building the UI

  6. Implementing the Shimmer Effect Flutter

  7. Displaying the Content

  8. Complete Code Snippet

  9. Conclusion


Before we start writing code, let's ensure that you have Flutter set up on your machine. Follow these steps to get started:


 flutter create shimmer_example 

In my case i named my project shimmer_example you can give whatever you want. Navigate to the project directory: 



cd shimmer_example 


Adding Dependencies:


We will use two packages in this project: google_fonts for custom fonts and shimmer for the shimmer effect Flutter. Add these dependencies to your pubspec.yaml file:



dependencies:
  flutter:
    sdk: flutter
  google_fonts: ^3.0.1
  shimmer: ^2.0.0
  url_launcher: ^6.2.6 


Run flutter pub get to install the packages.


Building the UI


Let's start by building the basic UI for our app. We will create a simple list that will display items with a shimmer effect while the content is loading.


Create a new file named list_item.dart in the lib directory:



// list_item.dart
class ListItem {
  final String description;
  final String url;
  final String images;

  ListItem({required this.description, required this.url, required this.images});
}

final List<ListItem> items = [
  ListItem(
    description: 'Permaculture Camping hostel & more',
    url: 'https://www.behance.net/gallery/135408901/ALDEA-VENADO',
    images: 'assets/Image1.png',
  ),
  // Add more items here
];


Now, create the main app UI in the main.dart file:


 
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:shimmer/shimmer.dart';
import 'list_item.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        appBar: AppBar(
          backgroundColor: Colors.white,
          elevation: 0,
          title: Text(
            'Shimmer Effect',
            style: GoogleFonts.poppins(
                fontSize: 20, color: Colors.black, fontWeight: FontWeight.bold),
          ),
        ),
        body: ShimmerList(),
      ),
    );
  }
}


Implementing the Shimmer Effect


Next, we'll create a shimmer effect while the content is loading. We'll simulate a network call by using a delay.


Create a new file named shimmer_list.dart in the lib directory:


 
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:shimmer/shimmer.dart';
import 'list_item.dart';

class ShimmerList extends StatefulWidget {
  @override
  _ShimmerListState createState() => _ShimmerListState();
}

class _ShimmerListState extends State<ShimmerList> {
  bool _isLoading = true;

  @override
  void initState() {
    super.initState();
    // Simulate a network call
    Timer(Duration(seconds: 10), () {
      setState(() {
        _isLoading = false;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      body: _isLoading ? _buildShimmerList() : _buildContentList(),
    );
  }

  Widget _buildShimmerList() {
    return ListView.builder(
      itemCount: items.length,
      itemBuilder: (context, index) {
        return Padding(
          padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0),
          child: Shimmer.fromColors(
            baseColor: Colors.grey[300]!,
            highlightColor: Colors.grey[100]!,
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Container(
                  decoration: BoxDecoration(
                    borderRadius: BorderRadius.circular(10),
                    color: Colors.white,
                  ),
                  height: 120.0,
                ),
                const SizedBox(height: 10.0),
                Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Container(
                      width: double.infinity,
                      height: 13.0,
                      color: Colors.white,
                    ),
                    const SizedBox(height: 8.0),
                    Container(
                      width: double.infinity,
                      height: 7.0,
                      color: Colors.white,
                    ),
                    const SizedBox(height: 8.0),
                    Container(
                      height: 7.0,
                      color: Colors.white,
                    ),
                  ],
                ),
              ],
            ),
          ),
        );
      },
    );
  }

  Widget _buildContentList() {
    return ListView.builder(
      itemCount: items.length,
      itemBuilder: (context, index) {
        final item = items[index];
        return Padding(
          padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0),
          child: Container(
            decoration: BoxDecoration(
              borderRadius: BorderRadius.all(Radius.circular(10)),
              color: Color.fromARGB(255, 191, 189, 189).withOpacity(0.2),
            ),
            child: Padding(
              padding: const EdgeInsets.all(8.0),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                mainAxisAlignment: MainAxisAlignment.start,
                children: [
                  GestureDetector(
                    onTap: () => _launchURL(item.url),
                    child: Container(
                      decoration: BoxDecoration(
                        color: Colors.white,
                        borderRadius: BorderRadius.circular(10),
                      ),
                      child: Padding(
                        padding: const EdgeInsets.all(5.0),
                        child: ClipRRect(
                          borderRadius: BorderRadius.circular(5),
                          child: Image.asset(
                            item.images,
                          ),
                        ),
                      ),
                    ),
                  ),
                  const SizedBox(height: 8.0),
                  Padding(
                    padding: const EdgeInsets.all(8.0),
                    child: Text(
                      item.description,
                      style: GoogleFonts.poppins(
                          fontSize: 14.0, color: Colors.black),
                    ),
                  ),
                ],
              ),
            ),
          ),
        );
      },
    );
  }
} 


Displaying the Content


We need to add a function to launch the URL when an item is clicked. This function can be added to the _ShimmerListState class.


 
Future<void> _launchURL(String url) async {
  if (await canLaunch(url)) {
    await launch(url);
  } else {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(content: Text('Could not launch $url')),
    );
  }
}


Complete Code Snippet


Here is the complete code for the Flutter app with the shimmer effect:



// main.dart
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:shimmer/shimmer.dart';
import 'list_item.dart';
import 'shimmer_list.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        appBar: AppBar(
          backgroundColor: Colors.white,
          elevation: 0,
          title: Text(
            'Shimmer Effect',
            style: GoogleFonts.poppins(
                fontSize: 20, color: Colors.black, fontWeight: FontWeight.bold),
          ),
        ),
        body: ShimmerList(),
      ),
    );
  }
}

// list_item.dart
class ListItem {
  final String description;
  final String url;
  final String images;

  ListItem({required this.description, required this.url, required this.images});
}

final List<ListItem> items = [
  ListItem(
    description: 'Permaculture Camping hostel & more',
    url: 'https://www.behance.net/gallery/135408901/ALDEA-VENADO',
    images: 'assets/Image1.png',
  ),
  ListItem(
    description: 'Branding, Redesign & Visual Identity',
    url: 'https://www.behance.net/gallery/164870245/Burguer-Ponto',
    images: 'assets/Image2.png',
  ),
  ListItem(
    images: 'assets/Image3.png',
    description: 'Eating meat is a thing to decompress and release emotions.',
    url: 'https://www.behance.net/gallery/156524781/Meat-Now-Company',
  ),
  ListItem(
    images: 'assets/Image4.png',
    description: 'Woohoop is a leading company in customized packaging',
    url: 'https://www.behance.net/gallery/197730331/Woohoop',
  ),
  ListItem(
    images: 'assets/Image5.png',
    description: 'Lorem ipsum is placeholder text commonly used in the graphic',
    url: 'https://www.behance.net/gallery/190466121/Hows-Coffee-Packaging-Design',
  ),
  ListItem(
    images: 'assets/Image6.png',
    description: 'Lorem ipsum is placeholder text commonly used in the graphic',
    url: 'https://www.behance.net/gallery/193952673/Design360-Magazine-No105-Award3602023-BEST-100',
  ),
  ListItem(
    images: 'assets/Image7.png',
    description: 'Lorem ipsum is placeholder text commonly used in the graphic',
    url: 'https://www.behance.net/gallery/166243201/Juicy-Fruit',
  ),
  ListItem(
    images: 'assets/Image8.png',
    description: 'Lorem ipsum is placeholder text commonly used in the graphic',
    url: 'https://www.behance.net/gallery/171606499/Outcore',
  ),
  ListItem(
    images: 'assets/Image9.png',
    description: 'Lorem ipsum is placeholder text commonly used in the graphic',
    url: 'https://www.behance.net/gallery/181729429/SNEAKERHEADZ',
  ),
  ListItem(
    images: 'assets/Image10.png',
    description: 'Lorem ipsum is placeholder text commonly used in the graphic',
    url: 'https://www.behance.net/gallery/194723063/Slanted-Special-Issue-GeorgiaArmenia',
  ),
];

// shimmer_list.dart
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:shimmer/shimmer.dart';
import 'list_item.dart';

class ShimmerList extends StatefulWidget {
  @override
  _ShimmerListState createState() => _ShimmerListState();
}

class _ShimmerListState extends State<ShimmerList> {
  bool _isLoading = true;

  @override
  void initState() {
    super.initState();
    // Simulate a network call
    Timer(Duration(seconds: 10), () {
      setState(() {
        _isLoading = false;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      body: _isLoading ? _buildShimmerList() : _buildContentList(),
    );
  }

  Widget _buildShimmerList() {
    return ListView.builder(
      itemCount: items.length,
      itemBuilder: (context, index) {
        return Padding(
          padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0),
          child: Shimmer.fromColors(
            baseColor: Colors.grey[300]!,
            highlightColor: Colors.grey[100]!,
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Container(
                  decoration: BoxDecoration(
                    borderRadius: BorderRadius.circular(10),
                    color: Colors.white,
                  ),
                  height: 120.0,
                ),
                const SizedBox(height: 10.0),
                Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Container(
                      width: double.infinity,
                      height: 13.0,
                      color: Colors.white,
                    ),
                    const SizedBox(height: 8.0),
                    Container(
                      width: double.infinity,
                      height: 7.0,
                      color: Colors.white,
                    ),
                    const SizedBox(height: 8.0),
                    Container(
                      height: 7.0,
                      color: Colors.white,
                    ),
                  ],
                ),
              ],
            ),
          ),
        );
      },
    );
  }

  Widget _buildContentList() {
    return ListView.builder(
      itemCount: items.length,
      itemBuilder: (context, index) {
        final item = items[index];
        return Padding(
          padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0),
          child: Container(
            decoration: BoxDecoration(
              borderRadius: BorderRadius.all(Radius.circular(10)),
              color: Color.fromARGB(255, 191, 189, 189).withOpacity(0.2),
            ),
            child: Padding(
              padding: const EdgeInsets.all(8.0),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                mainAxisAlignment: MainAxisAlignment.start,
                children: [
                  GestureDetector(
                    onTap: () => _launchURL(item.url),
                    child: Container(
                      decoration: BoxDecoration(
                        color: Colors.white,
                        borderRadius: BorderRadius.circular(10),
                      ),
                      child: Padding(
                        padding: const EdgeInsets.all(5.0),
                        child: ClipRRect(
                          borderRadius: BorderRadius.circular(5),
                          child: Image.asset(
                            item.images,
                          ),
                        ),
                      ),
                    ),
                  ),
                  const SizedBox(height: 8.0),
                  Padding(
                    padding: const EdgeInsets.all(8.0),
                    child: Text(
                      item.description,
                      style: GoogleFonts.poppins(
                          fontSize: 14.0, color: Colors.black),
                    ),
                  ),
                ],
              ),
            ),
          ),
        );
      },
    );
  }

  Future<void> _launchURL(String url) async {
    if (await canLaunch(url)) {
      await launch(url);
    } else {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Could not launch $url')),
      );
    }
  }
} 


PROJECT DEMO VIDEO:






Conclusion: 


In this comprehensive guide, we've covered the steps to create a Flutter app with a shimmer effect. This effect enhances the user experience by providing a visual placeholder while content is loading. By following this guide, you'll be able to implement a similar shimmer effect in your own Flutter applications. That's it. This is How we achieve How to Implement shimmer effect flutter in our Flutter App.


Happy coding ❤️


Aarthi Krishnan

Comments


bottom of page