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

如何在Flutter中实现滚动列表下方的粘性文本?

实现列表下方文本自适应布局(少时紧贴列表,多时固定底部)

你需要的效果是:列表项少的时候,文本紧跟在列表后面无空隙;列表项多的时候,文本固定在屏幕底部。之前的两种尝试都有问题:

  • 用Expanded包裹ListView:列表项少的时候,文本会被硬塞到屏幕底部,多出不必要的空隙
  • 移除Expanded加shrinkWrap: true:列表项多的时候直接溢出屏幕,无法正常显示

下面给你两种可行的解决方案,按需选择:

方案一:文本随列表内容自适应位置

这种方案下,列表内容少的时候文本紧贴列表;内容多的时候,列表占满剩余空间可滚动,文本被推到屏幕底部(需滚动列表才能看到)。

完整代码:

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: ItemListScreen(),
    );
  }
}

class ItemListScreen extends StatelessWidget {
  const ItemListScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('App'),
      ),
      body: Column(
        children: [
          // 用Flexible替代Expanded,允许ListView根据内容调整高度
          Flexible(
            child: ListView.builder(
              shrinkWrap: true,
              // 强制列表始终可滚动,避免内容不足时交互不一致
              physics: const AlwaysScrollableScrollPhysics(),
              itemCount: 30, // 修改数值可测试两种场景
              itemBuilder: (BuildContext context, int index) {
                return ListTile(title: Text('Item $index'));
              },
            ),
          ),
          const Text('This is some text below the list.'),
        ],
      ),
    );
  }
}

原理说明:

  • Flexible:和Expanded不同,它不会强制子组件占满所有可用空间,而是让ListView根据自身内容大小调整高度。内容少时,ListView只占实际需要的空间,文本自然紧贴;内容多时,ListView占满剩余空间并支持滚动。
  • shrinkWrap: true:让ListView根据子项总高度计算自身高度,而非默认占满父容器。
  • AlwaysScrollableScrollPhysics():确保即使列表内容不足,也能保持滚动的交互逻辑(不需要可移除,建议保留保证交互一致性)。

方案二:文本始终固定在屏幕底部

如果需要文本不管列表怎么滚动都固定在屏幕底部,不会被列表内容遮挡,可以用Stack实现:

完整代码:

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: ItemListScreen(),
    );
  }
}

class ItemListScreen extends StatelessWidget {
  const ItemListScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('App'),
      ),
      body: Stack(
        children: [
          // 列表底部留出文本高度,避免内容被遮挡
          ListView.builder(
            padding: const EdgeInsets.only(bottom: 40),
            itemCount: 30,
            itemBuilder: (BuildContext context, int index) {
              return ListTile(title: Text('Item $index'));
            },
          ),
          // 固定在屏幕底部的文本
          Positioned(
            left: 0,
            right: 0,
            bottom: 0,
            child: Container(
              padding: const EdgeInsets.all(16),
              color: Theme.of(context).scaffoldBackgroundColor, // 用背景色覆盖列表内容,避免遮挡
              child: const Text('This is some text below the list.'),
            ),
          ),
        ],
      ),
    );
  }
}

原理说明:

  • 用Stack将列表和文本层叠,列表通过padding在底部留出文本的高度,防止最后一项被遮挡。
  • 通过Positioned将文本固定在屏幕底部,无论列表如何滚动,文本始终可见。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 21:35:09