如何在 Flutter 的模态底部 Sheet 内向列表视图构建器添加程序化滚动?

How can I add a programmatic scroll down to a list view builder which is inside a Modal Bottom Sheet in Flutter?

我正在使用模态底部 sheet 来显示用户面临的挑战列表。当用户点击一个图标时:底部 sheet 出现并且列表建立。这一切都很好。

我在另一个列表的主屏幕上使用 scrollController。当用户添加一个项目时,我调用 _scrollDown(),这是我创建的一种用于自动向下滚动(在主屏幕上)的方法,它工作正常。 我想要底部 sheet 中的相同行为。问题是我不知道在哪里可以调用我的 _scrollDown() 方法。用户点击“我的挑战”,然后底部 sheet 出现并构建列表......然后它应该向下滚动......但我看不到代码中可以添加方法的位置...

这是模式 sheet 代码:(手势检测器位于用于获取挑战列表的图标上)

 GestureDetector(
                  onTap: () {
                    showModalBottomSheet<void>(
                      isScrollControlled: true,
                      shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.only(
                          topLeft: Radius.circular(20.0),
                          topRight: Radius.circular(20.0),
                        ),
                      ),
                      context: context,
                      builder: (BuildContext context) {
                        return Container(
                          height: MediaQuery.of(context).size.height - 80,
                          child: SingleChildScrollView(
                            padding: EdgeInsets.only(
                                bottom:
                                    MediaQuery.of(context).viewInsets.bottom),
                            child: Column(
                              mainAxisAlignment: MainAxisAlignment.center,
                              children: <Widget>[
                                Container(
                                  alignment: Alignment.topRight,
                                  child: IconButton(
                                      icon: Icon(
                                        Icons.cancel,
                                        color: Colors.red[900],
                                        size: uD.largeFont3,
                                      ),
                                      onPressed: () {
                                        Navigator.pop(context);
                                      }),
                                ),
                                Container(
                                  alignment: Alignment.topCenter,
                                  margin: const EdgeInsets.only(bottom: 20),
                                  child: Text(
                                    uD.selectedIoLanguage == Language.french
                                        ? 'Mes défis'.toUpperCase()
                                        : 'My Challenges'.toUpperCase(),
                                    textAlign: TextAlign.center,
                                    style: TextStyle(
                                      color: Colors.indigo[900],
                                      fontSize: uD.largeFont3,
                                    ),
                                  ),
                                ),
                                Container(
                                  decoration: BoxDecoration(
                                      border: Border(
                                          top: BorderSide(
                                        color: Colors.orange[200]!,
                                        width: 3,
                                      )),
                                      gradient: LinearGradient(
                                          colors: [
                                            Colors.orange[200]!,
                                            Colors.orange[50]!,
                                            Colors.orange[100]!,
                                            Colors.orange[200]!
                                          ],
                                          begin: Alignment.topLeft,
                                          end: Alignment.bottomLeft,
                                          stops: [0, 0.2, 0.5, 0.8])),
                                  height:
                                      MediaQuery.of(context).size.height - 163,
                                  child: uD.defis.length > 0
                                      ? ListView.builder(
                                          controller: _scrollController,
                                          cacheExtent: 2000,
                                          padding: const EdgeInsets.all(20),
                                          itemCount: uD.defis.length,
                                          itemBuilder: (context, index) {
                                            return MyDefisCard(
                                              index: index,
                                              score: uD.defis[index].score,
                                              date: uD.defis[index].date,
                                              time: uD.defis[index].time,

将你的底部 sheet 生成器结果移动到一个 StatefulWidget 中,假设它被称为 BottomSheetContent

showModalBottomSheet<void>(
  isScrollControlled: true,
  shape: const RoundedRectangleBorder(
    borderRadius: BorderRadius.only(
      topLeft: Radius.circular(20.0),
      topRight: Radius.circular(20.0),
    ),
  ),
  context: context,
  builder: (BuildContext context) => BottomSheetContent(),
);

在新的小部件中,创建一个新的 ScrollController(请注意,在您的代码中,您使用的是与之前路由列表中相同的 ScrollController)

class _BottomSheetContentState extends State<BottomSheetContent> {
  ScrollController _scrollController = ScrollController();
  @override
  void initState() {
    super.initState();

    WidgetsBinding.instance!.addPostFrameCallback((_) {
      // _scrollController.animateTo()
      // same logic as in _scrollDown
    });
  }

  @override
  Widget build(BuildContext context) {
    // return bottom sheet content 
  }
}