Mervin Hemaraju
Mervin Hemaraju

Reputation: 2117

Flutter CarouselView and Indicator with CarouselController

I am trying to implement a carousel indicator with my CarouselView but i am unable to get the current index. My code is as below:

class WelcomeScreen extends ConsumerStatefulWidget {
  const WelcomeScreen({super.key});

  @override
  ConsumerState<WelcomeScreen> createState() => WelcomeScreenState();
}

class WelcomeScreenState extends ConsumerState<WelcomeScreen> {
  int currentIndex = 0;
  final carouselController = CarouselController();

  @override
  void initState() {
    super.initState();
    carouselController.addListener(() {
      // Set the current index here
    });
  }

// Don't forget to dispose
  @override
  void dispose() {
    carouselController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final scaffoldKey = GlobalKey<ScaffoldState>();
    final theme = Theme.of(context);

    return Scaffold(
      key: scaffoldKey,
      body: SingleChildScrollView(
        scrollDirection: Axis.vertical,
        child: SafeArea(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              SizedBox(
                height: 240,
                child: CarouselView(
                  controller: carouselController,
                  padding: EdgeInsets.all(12.0),
                  itemExtent: MediaQuery.sizeOf(context).width,
                  itemSnapping: true,
                  children: List.generate(5, (index) {
                    setState(() {
                      currentIndex = index;
                    });
                    return Container(
                      color: theme.colorScheme.surfaceContainer,
                    );
                  }),
                ),
              ),
              Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: List.generate(5, (index) {
                  return AnimatedContainer(
                    duration: const Duration(milliseconds: 300),
                    margin: const EdgeInsets.symmetric(horizontal: 4),
                    height: 8,
                    width:
                        currentIndex == index ? 24 : 8, // Make active dot wider
                    decoration: BoxDecoration(
                      borderRadius: BorderRadius.circular(4),
                      color: currentIndex == index
                          ? theme.colorScheme.primary
                          : theme.colorScheme.tertiary,
                    ),
                  );
                }),
              )
            ],
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        elevation: MesElevation.fab,
        backgroundColor: theme.colorScheme.primary,
        foregroundColor: theme.colorScheme.onPrimary,
        onPressed: () {},
        shape: CircleBorder(),
        child: Icon(Icons.arrow_forward_ios_outlined),
      ),
      floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
    );
  }
}

I see that there is a position attribute in the controller but it returns the ScrollPosition type and i don't know how to get the index from this to update my indicator view.

Any one can help please?

Upvotes: 0

Views: 161

Answers (2)

pardeep solution
pardeep solution

Reputation: 1

       CarouselSlider(
                  carouselController: carouselController,
                  options: CarouselOptions(
                    height: 240,
                    onPageChanged: (index, reason) {
                      setState(() {
                        currentIndex = index; 
                      });
                    },
                  ),
                  items: List.generate(5, (index) {
                    return Container(
                      color: theme.colorScheme.surfaceContainer,
                      child: Center(child: Text('Item $index')), 
                    );
                  }),
                ),
              ),
        floatingActionButton: FloatingActionButton(
        elevation: 6,
        backgroundColor: theme.colorScheme.primary,
        foregroundColor: theme.colorScheme.onPrimary,
        onPressed: () {
        
          if (currentIndex < 4) {
            carouselController.nextPage();
          }
        },
        shape: CircleBorder(),
        child: Icon(Icons.arrow_forward_ios_outlined),
      ),
      floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
    );

Upvotes: 0

Meshkat Shadik
Meshkat Shadik

Reputation: 337

Do something like this to the CarouselController listener,

       controller.addListener(() {
            final position = controller.position;
            final width = MediaQuery.sizeOf(context).width - 32; //your width
            if (position.hasPixels) {
              final index = (position.pixels / width).round();
              setState(() {
                currentIndex.value = index;
              });
            }
          });

Rest of the stuff you've write seems good to go!

I personally prefer in this case, making a Mixin that has other logic like

  • Auto scrolling
  • Current Index (etc)

Upvotes: 1

Related Questions