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

Flutter实现黄色与红色横向ListView同步滚动需求咨询

Flutter 横向ListView同步滚动实现方案

需求:当滚动黄色行或任意红色行的横向ListView时,所有红色行与黄色行的横向列表同步滚动。

实现思路

给每个横向ListView分配独立的ScrollController,通过监听所有控制器的滚动事件,同步所有列表的滚动偏移量,同时使用标志位避免循环触发监听逻辑。

完整实现代码

import 'package:flutter/material.dart';

class SyncHorizontalListView extends StatefulWidget {
  const SyncHorizontalListView({super.key});

  @override
  State<SyncHorizontalListView> createState() => _SyncHorizontalListViewState();
}

class _SyncHorizontalListViewState extends State<SyncHorizontalListView> {
  late ScrollController _yellowScrollController;
  final List<ScrollController> _redScrollControllers = [];
  bool _isSyncing = false; // 防止循环触发滚动监听

  @override
  void initState() {
    super.initState();
    // 初始化黄色区域的滚动控制器
    _yellowScrollController = ScrollController();
    _yellowScrollController.addListener(_syncScroll);

    // 初始化32个红色区域的滚动控制器并添加监听
    for (int i = 0; i < 32; i++) {
      final controller = ScrollController();
      _redScrollControllers.add(controller);
      controller.addListener(_syncScroll);
    }
  }

  // 同步所有横向列表的滚动位置
  void _syncScroll() {
    if (_isSyncing) return;
    _isSyncing = true;

    // 获取当前正在滚动的列表的偏移量
    double currentOffset = 0;
    // 先检查黄色列表是否在滚动
    if (_yellowScrollController.hasClients && _yellowScrollController.position.isScrollingNotifier.value) {
      currentOffset = _yellowScrollController.offset;
    } else {
      // 遍历红色列表,找到正在滚动的那个
      for (final controller in _redScrollControllers) {
        if (controller.hasClients && controller.position.isScrollingNotifier.value) {
          currentOffset = controller.offset;
          break;
        }
      }
    }

    // 同步黄色列表的位置
    if (_yellowScrollController.hasClients && _yellowScrollController.offset != currentOffset) {
      _yellowScrollController.jumpTo(currentOffset);
    }

    // 同步所有红色列表的位置
    for (final controller in _redScrollControllers) {
      if (controller.hasClients && controller.offset != currentOffset) {
        controller.jumpTo(currentOffset);
      }
    }

    _isSyncing = false;
  }

  @override
  void dispose() {
    // 释放所有控制器资源
    _yellowScrollController.dispose();
    for (final controller in _redScrollControllers) {
      controller.dispose();
    }
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("同步横向列表"),
      ),
      body: LayoutBuilder(
        builder: (context, constraints) => Column(
          children: [
            SizedBox(
              height: 40,
              child: Row(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Expanded(
                    flex: 2,
                    child: Card(
                      child: Container(
                          width: 100,
                          height: 30,
                          color: Colors.green,
                          child: const Text("固定标签栏")),
                    ),
                  ),
                  Expanded(
                      flex: 4,
                      child: Padding(
                        padding: const EdgeInsets.all(4.0),
                        child: SizedBox(
                          height: 30,
                          child: ListView.builder(
                            itemCount: 20,
                            scrollDirection: Axis.horizontal,
                            controller: _yellowScrollController,
                            itemBuilder: (context, index) {
                              return Container(
                                width: 100,
                                height: 30,
                                color: Colors.yellow,
                                child: Text("item $index"),
                              );
                            },
                          ),
                        ),
                      )),
                ],
              ),
            ),
            Expanded(
              child: ListView(
                children: [
                  for (int i = 0; i < 32; i++)
                    Row(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Expanded(
                          flex: 2,
                          child: Card(
                            child: Container(
                                width: 100,
                                height: 30,
                                color: Colors.blue,
                                child: const Text("固定内容栏")),
                          ),
                        ),
                        Expanded(
                            flex: 4,
                            child: Padding(
                              padding: const EdgeInsets.all(4.0),
                              child: SizedBox(
                                height: 30,
                                child: ListView.builder(
                                  itemCount: 20,
                                  scrollDirection: Axis.horizontal,
                                  controller: _redScrollControllers[i],
                                  itemBuilder: (context, index) {
                                    return Container(
                                      width: 100,
                                      height: 30,
                                      color: Colors.red,
                                      child: Text("item $index"),
                                    );
                                  },
                                ),
                              ),
                            )),
                      ],
                    ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

UI效果截图

UI截图

关键说明

  1. 控制器管理:为黄色列表和每个红色列表分别创建ScrollController,统一管理并添加滚动监听。
  2. 同步逻辑:当任意列表滚动时,获取当前偏移量,调用jumpTo方法同步其他所有列表的位置。
  3. 避免循环触发:使用_isSyncing标志位,在同步过程中跳过监听回调,防止重复触发同步逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 05:57:22