'GlobalKey().currentContext' 在 ListWheelScrollView 中为 null

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

我正在尝试 select/scroll 在单击按钮时自动转到 ListWheelScrollView 中的特定元素。它适用于当前页面中显示的元素。但是我一直遇到由于延迟加载导致列表超出屏幕的问题。

由于 ListWheelScrollView 中的小部件未呈现,当尝试滚动到屏幕之外时会为当前上下文抛出 null 错误。

我尝试过的:

尝试 1:我尝试将 ListWheelScrollView 包装在 SingleChildScrollView 小部件中。没有解决问题。

尝试 2:尝试使用 (scrollable_positioned_list )。它用于 ListView 而不是 ListWheelScrollView。

这是我的源代码。

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"),
                    ),
                  ),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}

任何 help/suggestion 将不胜感激。谢谢!

在做了一些基础工作后,我发现可以通过 FixedExtentScrollController 来完成。

如果有人面临同样的问题,这里是完整的例子。


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),
      ),
    );
  }
}