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

如何在Flutter的ListView.builder下方添加内容实现自然滚动

解决方法

有两种常用方案实现需求,以下是具体操作:

方案一:扩展ListView.builder的itemCount(简单直接)

直接修改itemCount和itemBuilder的判断逻辑,把底部内容作为最后一个列表项:

修改要点:

  1. 将itemCount从services.length + 1改为services.length + 2(1个顶部标题 + N个服务项 + 1个底部内容)
  2. 在itemBuilder中新增判断逻辑,当index等于总项数-1时,返回底部内容

修改后的完整代码:

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: const Text(
        'Home',
        style: TextStyle(color: Colors.white),
      ),
      backgroundColor: Colors.deepPurple,
    ),
    body: _isLoading
        ? const Center(
            child: CircularProgressIndicator(),
          )
        : ListView.builder(
            itemCount: services.length + 2, // +1标题 +1底部内容
            itemBuilder: (context, index) {
              if (index == 0) {
                // 顶部标题
                return const Padding(
                  padding: EdgeInsets.only(top: 30.0, bottom: 12),
                  child: Center(
                    child: Text(
                      'Services',
                      style: TextStyle(fontSize: 29),
                    ),
                  ),
                );
              } else if (index == services.length + 1) {
                // 底部内容:关于板块+页脚
                return Container(
                  padding: const EdgeInsets.symmetric(vertical: 30, horizontal: 20),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.center,
                    children: const [
                      Text(
                        '关于我们',
                        style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold),
                      ),
                      SizedBox(height: 16),
                      Text(
                        '我们致力于提供优质的服务,满足您的各类需求。',
                        style: TextStyle(fontSize: 16),
                        textAlign: TextAlign.center,
                      ),
                      SizedBox(height: 24),
                      Text(
                        '© 2025 自研App 版权所有',
                        style: TextStyle(fontSize: 14, color: Colors.grey),
                      ),
                    ],
                  ),
                );
              } else {
                // 服务项
                Service service = services[index - 1];
                var smallestDuration = findLowestDurationPrice(service);

                return Padding(
                  padding: const EdgeInsets.all(20),
                  child: Card(
                    shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(15),
                    ),
                    child: ClipRRect(
                      borderRadius: BorderRadius.circular(20),
                      child: Column( // 移除原代码内部的SingleChildScrollView,避免滚动冲突
                        children: [
                          FutureBuilder(
                            future: getImageUrl(service.imageFileName),
                            builder: (context, snapshot) {
                              if (snapshot.connectionState == ConnectionState.waiting) {
                                return const CircularProgressIndicator();
                              } else if (snapshot.hasError) {
                                return Text('Error: ${snapshot.error}');
                              } else {
                                String imageUrl = snapshot.data.toString();
                                return Container(
                                  height: 270,
                                  child: Image.network(
                                    imageUrl,
                                    fit: BoxFit.cover,
                                  ),
                                );
                              }
                            },
                          ),
                          ExpansionTile(
                            title: Text(
                              service.title,
                              style: const TextStyle(fontSize: 20),
                            ),
                            children: [
                              Padding(
                                padding: const EdgeInsets.all(17.0),
                                child: Text(
                                  service.description,
                                  style: const TextStyle(fontSize: 16),
                                ),
                              ),
                              Padding(
                                padding: const EdgeInsets.all(17.0),
                                child: Row(
                                  children: [
                                    const Text('Starting from:'),
                                    const SizedBox(width: 8),
                                    Text(
                                      '€ $smallestDuration',
                                      style: const TextStyle(fontSize: 16),
                                    ),
                                  ],
                                ),
                              ),
                            ],
                          ),
                        ],
                      ),
                    ),
                  ),
                );
              }
            },
          ),
  );
}

额外优化提示:

原代码中服务卡片内部的SingleChildScrollView可以移除,因为外层已经是ListView负责滚动,嵌套会导致不必要的滚动冲突。


方案二:使用CustomScrollView(更灵活,适合多段滚动内容)

如果需要添加更多分段内容(比如中间的广告、分类标题),推荐用CustomScrollView结合Sliver组件,滚动体验更流畅:

示例代码:

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: const Text(
        'Home',
        style: TextStyle(color: Colors.white),
      ),
      backgroundColor: Colors.deepPurple,
    ),
    body: _isLoading
        ? const Center(child: CircularProgressIndicator())
        : CustomScrollView(
            slivers: [
              // 顶部标题
              SliverToBoxAdapter(
                child: const Padding(
                  padding: EdgeInsets.only(top: 30.0, bottom: 12),
                  child: Center(
                    child: Text(
                      'Services',
                      style: TextStyle(fontSize: 29),
                    ),
                  ),
                ),
              ),
              // 服务列表
              SliverList.builder(
                itemCount: services.length,
                itemBuilder: (context, index) {
                  Service service = services[index];
                  var smallestDuration = findLowestDurationPrice(service);
                  // 返回服务卡片(去掉内部SingleChildScrollView)
                  return Padding(
                    padding: const EdgeInsets.all(20),
                    child: Card(
                      shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(15),
                      ),
                      child: ClipRRect(
                        borderRadius: BorderRadius.circular(20),
                        child: Column(
                          children: [
                            FutureBuilder(
                              future: getImageUrl(service.imageFileName),
                              builder: (context, snapshot) {
                                if (snapshot.connectionState == ConnectionState.waiting) {
                                  return const CircularProgressIndicator();
                                } else if (snapshot.hasError) {
                                  return Text('Error: ${snapshot.error}');
                                } else {
                                  String imageUrl = snapshot.data.toString();
                                  return Container(
                                    height: 270,
                                    child: Image.network(
                                      imageUrl,
                                      fit: BoxFit.cover,
                                    ),
                                  );
                                }
                              },
                            ),
                            ExpansionTile(
                              title: Text(
                                service.title,
                                style: const TextStyle(fontSize: 20),
                              ),
                              children: [
                                Padding(
                                  padding: const EdgeInsets.all(17.0),
                                  child: Text(
                                    service.description,
                                    style: const TextStyle(fontSize: 16),
                                  ),
                                ),
                                Padding(
                                  padding: const EdgeInsets.all(17.0),
                                  child: Row(
                                    children: [
                                      const Text('Starting from:'),
                                      const SizedBox(width: 8),
                                      Text(
                                        '€ $smallestDuration',
                                        style: const TextStyle(fontSize: 16),
                                      ),
                                    ],
                                  ),
                                ),
                              ],
                            ),
                          ],
                        ),
                      ),
                    ),
                  );
                },
              ),
              // 底部内容
              SliverToBoxAdapter(
                child: Container(
                  padding: const EdgeInsets.symmetric(vertical: 30, horizontal: 20),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.center,
                    children: const [
                      Text(
                        '关于我们',
                        style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold),
                      ),
                      SizedBox(height: 16),
                      Text(
                        '我们致力于提供优质的服务,满足您的各类需求。',
                        style: TextStyle(fontSize: 16),
                        textAlign: TextAlign.center,
                      ),
                      SizedBox(height: 24),
                      Text(
                        '© 2025 自研App 版权所有',
                        style: TextStyle(fontSize: 14, color: Colors.grey),
                      ),
                    ],
                  ),
                ),
              ),
            ],
          ),
  );
}

方案优势:

  • 可以灵活添加多个分段内容(比如中间插入SliverAppBar、SliverGrid等)
  • 滚动性能更优,适合复杂页面结构

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 16:58:14