# Building a Smooth Animated Image Carousel in Flutter

By | March 4, 2025

Introduction

A well-designed image carousel can greatly enhance the user experience in Flutter apps.

In this article, we will create a **beautiful and interactive image slider** using **CarouselController**.

We’ll add smooth animations, navigation buttons, and loading indicators to improve usability.

Prerequisites

To follow along, make sure you have Flutter installed.

If you haven’t set it up yet, check out the [official Flutter installation guide](https://flutter.dev/docs/get-started/install).

Step 1: Setting Up the Project

Create a new Flutter project or use an existing one.

flutter create carousel_demo

cd carousel_demo

Step 2: Adding Dependencies

No third party dependencies are needed.

Step 3: Implementing the Image Carousel

Now, let’s create a stateful widget to handle the carousel functionality.

Below is the complete **Home** widget, which includes navigation buttons, smooth animations, and image loading indicators.

Full Code

import 'package:flutter/material.dart';

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

  @override
  State<Home> createState() => _HomeState();
}

class _HomeState extends State<Home> {
  CarouselController carouselController = CarouselController();

  List<String> images = [
    "https://images.unsplash.com/photo-1503376780353-7e6692767b70",
    "https://images.unsplash.com/photo-1577714141096-bf2b9e69500a",
    "https://images.unsplash.com/photo-1542362567-b07e54358753",
    "https://images.unsplash.com/photo-1511407397940-d57f68e81203",
    "https://images.unsplash.com/photo-1659671026913-b7e632f17395"
  ];

  double itemSize = 330;
  double shrinkSize = 200;
  double totalSize = 0;
  double prevPosition = 0;

  @override
  void initState() {
    super.initState();
    totalSize = itemSize * images.length;
  }

  void moveTo(double newPos) {
    // carouselController.jumpTo(newPos);
    carouselController.animateTo(
      newPos,
      duration: const Duration(seconds: 1),
      curve: Curves.easeIn,
    );
    prevPosition = newPos;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Carousel'),
      ),
      body: Column(
        children: [
          ConstrainedBox(
            constraints: const BoxConstraints(maxHeight: 200),
            child: CarouselView(
              controller: carouselController,
              itemExtent: itemSize,
              shrinkExtent: shrinkSize,
              enableSplash: true,
              scrollDirection: Axis.horizontal,
              children: List.generate(
                images.length,
                (index) {
                  return Image.network(
                    images[index],
                    filterQuality: FilterQuality.high,
                    fit: BoxFit.cover,
                    loadingBuilder: (context, child, loadingProgress) {
                      if (null == loadingProgress) {
                        return child;
                      }
                      final totalBytes =
                          loadingProgress.expectedTotalBytes ?? 1;
                      final loadedBytes = loadingProgress.cumulativeBytesLoaded;
                      final progress = loadedBytes / totalBytes;

                      return Column(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: [
                          CircularProgressIndicator(value: progress),
                          const SizedBox(height: 10),
                          Text('${(progress * 100).toStringAsFixed(0)}%'),
                        ],
                      );
                    },
                    errorBuilder: (context, error, stackTrace) {
                      return const Center(
                        child: Text('Failed to load image'),
                      );
                    },
                  );
                },
              ),
            ),
          ),
          const SizedBox(height: 20),
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              ElevatedButton(
                onPressed: () {
                  if (prevPosition > 0) moveTo(prevPosition - itemSize);
                },
                child: const Text('Prev'),
              ),
              const SizedBox(width: 20),
              ElevatedButton(
                onPressed: () {
                  final newPos = prevPosition + itemSize;
                  if (newPos < totalSize) moveTo(newPos);
                },
                child: const Text('Next'),
              ),
            ],
          ),
        ],
      ),
    );
  }
}

Step 4: Running the App

To run the app, execute the following command:

flutter run

Now, you should see a beautifully animated image slider with smooth transitions between slides.

Conclusion

In this tutorial, we built an animated image carousel in Flutter with smooth navigation, progress indicators, and interactive buttons.

This feature can be easily integrated into any Flutter app to enhance the user experience.

If you found this article helpful, feel free to share it! 🚀

Happy coding! 🎯

Leave a Reply

Your email address will not be published. Required fields are marked *