You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter技术问题:DraggableScrollableSheet无法上滑展开如何解决?

问题分析与解决方案

你的DraggableScrollableSheet无法上滑展开,核心问题在于滚动控制器冲突和参数配置错误,以下是具体修复步骤:

1. 使用Sheet提供的ScrollController

DraggableScrollableSheet的builder回调会传入专属的sheetScrollController,这个控制器用于联动Sheet大小调整和内部列表滚动。你当前用自定义scrollController绑定ListView,导致Sheet无法识别拖动手势,直接替换即可。

2. 修正expand参数

将expand: true改为expand: false,expand: true会让Sheet强制占满父容器,破坏其可拖动特性,只有设为false时,Sheet才会遵循initialChildSize/minChildSize/maxChildSize的配置。

3. 调整自动滚动逻辑

添加新闻后需要自动滚动到底部时,要使用Sheet提供的控制器执行滚动操作,同时通过addPostFrameCallback确保列表更新后再执行滚动。

修复后的完整代码

List<NewsEvent> newsList = [];
int newsID = 0;
bool isLightMode = true;
Color colourOnPrimary = Colors.white;
Color colourPrimaryLeastDark = Colors.grey[800]!;
GlobalKey<State> mapPageKey = GlobalKey();

class NewsEvent {
  final int id;
  final String event;
  final String timestamp;
  final Icon icon;

  NewsEvent({
    required this.id,
    required this.event,
    required this.timestamp,
    required this.icon,
  });
}

class NewsHandler {
  ScrollController? sheetScrollController;

  Widget newsFeed() {
    return DraggableScrollableSheet(
      initialChildSize: 0.1,
      minChildSize: 0.1,
      maxChildSize: 0.66,
      snap: true,
      expand: false,
      builder: (context, ScrollController controller) {
        sheetScrollController = controller;
        return Container(
          decoration: BoxDecoration(
            borderRadius: const BorderRadius.only(
              topLeft: Radius.circular(12),
              topRight: Radius.circular(12),
            ),
            color: isLightMode ? colourOnPrimary : colourPrimaryLeastDark,
          ),
          child: Column(
            children: [
              Padding(
                padding: const EdgeInsets.all(4.0),
                child: Container(
                  width: 50,
                  height: 3,
                  decoration: BoxDecoration(
                    borderRadius: BorderRadius.circular(12),
                    color: Colors.grey,
                  ),
                ),
              ),
              Expanded(
                child: ListView.builder(
                  physics: const ClampingScrollPhysics(),
                  controller: sheetScrollController,
                  itemCount: newsList.length,
                  itemBuilder: (BuildContext context, int index) {
                    NewsEvent newsEvent = newsList[index];
                    TextStyle eventStyle = const TextStyle(fontSize: 16, color: Colors.black);
                    TextStyle timestampStyle = const TextStyle(fontSize: 12, fontStyle: FontStyle.italic, color: Colors.black);

                    return Column(
                      children: [
                        const SizedBox(height: 5, width: 300, child: Divider(color: Color.fromARGB(123, 158, 158, 158))),
                        ListTile(
                          leading: newsEvent.icon,
                          title: Row(
                            children: [
                              Expanded(
                                child: Text(newsEvent.event, style: eventStyle),
                              ),
                              Text(newsEvent.timestamp, style: timestampStyle),
                            ],
                          ),
                        ),
                      ],
                    );
                  },
                ),
              ),
            ],
          ),
        );
      },
    );
  }

  void addNews(String event, Icon icon) {
    String timestamp = DateFormat.jm().format(DateTime.now());
    newsList.add(NewsEvent(id: newsID, event: event, timestamp: timestamp, icon: icon));
    newsID++;

    MapPageState? mapPageState = mapPageKey.currentState as MapPageState?;
    mapPageState?.mapPageSetState();
    
    WidgetsBinding.instance.addPostFrameCallback((_) {
      scrollDown();
    });
  }

  void scrollDown(){
    if(sheetScrollController != null && sheetScrollController!.hasClients){
      sheetScrollController!.animateTo(
        sheetScrollController!.position.maxScrollExtent,
        duration: const Duration(milliseconds: 500),
        curve: Curves.easeInOut,
      );
    }
  }
}

class MapPageState extends State {
  void mapPageSetState() {
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return const SizedBox();
  }
}

额外说明

  • 当ListView滚动到顶部时,继续上滑会触发Sheet展开;Sheet展开状态下,向下滚动ListView到顶部后继续下滑,会触发Sheet收起。
  • 补充了代码中缺失的变量,确保代码可直接运行测试。

内容的提问来源于stack exchange,提问作者RJrules64

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 11:32:50