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

Flutter列表滚动时如何固定分组标题并随当前显示分组动态切换

列表分组吸顶标题实现方案

核心实现思路

  • 监听列表容器的滚动事件
  • 计算每个分组区块距离容器顶部的偏移值,判断当前视口内处于展示状态的分组
  • 当分组顶部滚动到吸顶位置时,将对应标题固定在顶部,下一个分组顶上来的时候替换当前显示的标题

原生CSS最优实现方案

直接使用CSS原生position: sticky属性即可实现零JS逻辑的吸顶效果,兼容性覆盖95%以上现代浏览器,性能最优:

/* 列表容器 */
.list-container {
  height: 500px;
  overflow-y: auto;
}
/* 分组吸顶标题 */
.sticky-header {
  position: sticky;
  top: 0;
  background: #fff;
  padding: 8px 12px;
  font-weight: bold;
  z-index: 10;
  border-bottom: 1px solid #eee;
}
/* 分组内容 */
.group-item {
  padding: 0 12px;
}
/* 分组内子项 */
.group-child {
  padding: 12px 0;
  border-bottom: 1px solid #f5f5f5;
}

HTML结构示例:

<div class="list-container">
  <!-- 每个分组自带sticky标题即可自动实现切换吸顶 -->
  <div class="group">
    <div class="sticky-header">A</div>
    <div class="group-item">
      <div class="group-child">阿强</div>
      <div class="group-child">阿兰</div>
      <div class="group-child">阿飞</div>
    </div>
  </div>
  <div class="group">
    <div class="sticky-header">B</div>
    <div class="group-item">
      <div class="group-child">Bob</div>
      <div class="group-child">小白</div>
      <div class="group-child">包仔</div>
    </div>
  </div>
  <!-- 其余分组结构同上 -->
</div>

注意:使用position: sticky时,父级元素不能设置overflow: hidden属性,否则吸顶效果会失效。

低版本浏览器兼容JS实现方案

如果需要兼容IE等不支持sticky的旧浏览器,可以通过JS动态计算偏移实现:

const listContainer = document.getElementById('listContainer')
const groups = document.querySelectorAll('.group')
const headers = document.querySelectorAll('.sticky-header')

// 预先存储每个分组的顶部偏移值
const groupOffsets = Array.from(groups).map(group => group.offsetTop)

listContainer.addEventListener('scroll', () => {
  const scrollTop = listContainer.scrollTop
  // 匹配当前滚动位置对应的分组
  const currentGroupIndex = groupOffsets.findLastIndex(offset => offset <= scrollTop)
  
  if (currentGroupIndex >= 0) {
    // 实现标题被下一个分组顶走的交互动画
    const nextGroupOffset = groupOffsets[currentGroupIndex + 1]
    const headerHeight = headers[0].offsetHeight
    if (nextGroupOffset && nextGroupOffset - scrollTop < headerHeight) {
      headers[currentGroupIndex].style.transform = `translateY(${nextGroupOffset - scrollTop - headerHeight}px)`
    } else {
      headers.forEach(header => header.style.transform = 'translateY(0)')
    }
  }
})
  • 上述JS方案可以实现和原生sticky完全一致的切换效果,同时支持自定义切换动画
  • 如果在Vue、React等框架中使用,可以直接调用对应UI组件库的IndexBar索引栏组件,开箱即可实现联系人式的首字母吸顶效果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 15:48:03