'GlobalKey().currentContext' in ListWheelScrollView is null in flutter

Issue

I’m trying to select/scroll automatically to a particular element in ListWheelScrollView on a button click. It is working fine for the elements which are displayed in the current page. But I’ve been facing the issue when the list exceeds the screen due to lazy loading.

Due to widgets in ListWheelScrollView not rendered, when trying to scroll beyond the screen is throwing null error for the current context.

What I’ve tried:

Attempt 1: I’ve tried wrapping the ListWheelScrollView inside the SingleChildScrollView widget. Didn’t solve the issue.

Attempt 2: Tried out using (scrollable_positioned_list ). It is for the ListView and not for ListWheelScrollView.

Here is my source code.

import 'package:flutter/material.dart';
// import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';

void main() {
  runApp(
    const MaterialApp(home: StatefulWidgetsExample()), // use MaterialApp
  );
}

class StatefulWidgetsExample extends StatefulWidget {
  const StatefulWidgetsExample({Key? key}) : super(key: key);

  @override
  State<StatefulWidget> createState() => _StatefulWidgetsExampleState();
}

class _StatefulWidgetsExampleState extends State<StatefulWidgetsExample> {
  final itemKey = GlobalKey();
  final scrollController = ScrollController();

  Future animateTo() async {
    BuildContext? context = itemKey.currentContext;
    scrollController.position.ensureVisible(
      itemKey.currentContext!.findRenderObject()!,
      duration: const Duration(seconds: 1),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("List Wheel"),
      ),
      body: Column(
        children: [
          Expanded(
            child: Center(
              child: Row(
                children: [
                  SizedBox(
                    height: 500,
                    width: 200,
                    child: SingleChildScrollView(
                      scrollDirection: Axis.vertical,
                      child: SizedBox(
                        height: 500,
                        width: 200,
                        child: ListWheelScrollView(
                          controller: scrollController,
                          itemExtent: 100,
                          children: <Widget>[
                            const MaterialButton(
                              onPressed: null,
                              child: Text(
                                "Item 1",
                                textAlign: TextAlign.start,
                                style: TextStyle(
                                    color: Colors.black,
                                    fontWeight: FontWeight.bold,
                                    fontSize: 25),
                              ),
                            ),
                            const MaterialButton(
                              onPressed: null,
                              child: Text(
                                "Item 2",
                                textAlign: TextAlign.center,
                                style: TextStyle(
                                    color: Colors.black,
                                    fontWeight: FontWeight.bold,
                                    fontSize: 25),
                              ),
                            ),
                            const MaterialButton(
                              onPressed: null,
                              child: Text(
                                "Item 3",
                                textAlign: TextAlign.center,
                                style: TextStyle(
                                    color: Colors.black,
                                    fontWeight: FontWeight.bold,
                                    fontSize: 25),
                              ),
                            ),
                            const MaterialButton(
                              onPressed: null,
                              child: Text(
                                "Item 4",
                                textAlign: TextAlign.center,
                                style: TextStyle(
                                    color: Colors.black,
                                    fontWeight: FontWeight.bold,
                                    fontSize: 25),
                              ),
                            ),
                            Container(
                              alignment: Alignment.center,
                              key: itemKey,
                              child: const MaterialButton(
                                onPressed: null,
                                child: Text(
                                  "Item 5",
                                  textAlign: TextAlign.center,
                                  style: TextStyle(
                                      color: Colors.black,
                                      fontWeight: FontWeight.bold,
                                      fontSize: 25),
                                ),
                              ),
                            ),
                            const MaterialButton(
                              onPressed: null,
                              child: Text(
                                "Item 6",
                                textAlign: TextAlign.center,
                                style: TextStyle(
                                    color: Colors.black,
                                    fontWeight: FontWeight.bold,
                                    fontSize: 25),
                              ),
                            ),
                            const MaterialButton(
                              onPressed: null,
                              child: Text(
                                "Item 7",
                                textAlign: TextAlign.center,
                                style: TextStyle(
                                    color: Colors.black,
                                    fontWeight: FontWeight.bold,
                                    fontSize: 25),
                              ),
                            ),
                            const MaterialButton(
                              onPressed: null,
                              child: Text(
                                "Item 8",
                                textAlign: TextAlign.center,
                                style: TextStyle(
                                    color: Colors.black,
                                    fontWeight: FontWeight.bold,
                                    fontSize: 25),
                              ),
                            ),
                          ],
                          clipBehavior: Clip.hardEdge,
                        ),
                      ),
                    ),
                  ),
                  Padding(
                    padding: const EdgeInsets.all(8.0),
                    child: MaterialButton(
                      color: Colors.red,
                      onPressed: animateTo,
                      child: const Text("Animate to"),
                    ),
                  ),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}

Any help/suggestion would be highly appreciated. Thank you!

Solution

After doing a bit of ground work, I’ve figured out that it can be done through FixedExtentScrollController.

Here is the complete example if someone is facing the same issue.


void main() {
  runApp(
    const MaterialApp(home: StatefulWidgetsExample()), // use MaterialApp
  );
}

class StatefulWidgetsExample extends StatefulWidget {
  const StatefulWidgetsExample({Key? key}) : super(key: key);

  @override
  State<StatefulWidget> createState() => _StatefulWidgetsExampleState();
}

class _StatefulWidgetsExampleState extends State<StatefulWidgetsExample> {
  final FixedExtentScrollController scrollController =
      FixedExtentScrollController();

  @override
  void dispose() {
    scrollController.dispose();
    super.dispose();
  }

  Widget buildCard(int i) => Padding(
        padding: const EdgeInsets.all(8.0),
        child: Container(
          width: 200,
          height: 200,
          color: Colors.red,
          child: Center(
            child: Text(
              "Widget: " + i.toString(),
            ),
          ),
        ),
      );

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("List Wheel"),
      ),
      body: ListWheelScrollView(
        controller: scrollController,
        itemExtent: 250,
        physics: const FixedExtentScrollPhysics(),
        squeeze: 0.9,
        children: [
          buildCard(0),
          buildCard(1),
          buildCard(2),
          buildCard(3),
          buildCard(4),
          buildCard(5),
          buildCard(6),
          buildCard(7),
          buildCard(8),
          buildCard(9),
          buildCard(10),
          buildCard(11),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          scrollController.animateToItem(9,
              duration: const Duration(seconds: 1), curve: Curves.easeInOut);
        },
        child: const Icon(Icons.ac_unit),
      ),
    );
  }
}

Answered By – Srujan Chowdary Panda

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published