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

Flutter中如何跨页面访问ScrollController控制滚动视图

解决Flutter跨页面ScrollController滚动跳转问题

问题核心

你在TopBarContents里自己新建了ScrollController实例,这个控制器和主页面SingleChildScrollView绑定的控制器完全是两个独立对象,点击按钮时操作的是自己的控制器,自然影响不到主页面的滚动视图。

解决办法:把主页面的ScrollController传给自定义AppBar

第一步:改造TopBarContents,接收外部传入的控制器

import 'package:flutter/material.dart';

class TopBarContents extends StatefulWidget {
  // 接收主页面传过来的滚动控制器
  final ScrollController scrollController;

  const TopBarContents({super.key, required this.scrollController});

  @override
  _TopBarContentsState createState() => _TopBarContentsState();
}

class _TopBarContentsState extends State<TopBarContents> {
  final List _isHovering = [
    false,
    false,
    false,
    false,
    false,
    false,
    false,
    false
  ];

  // 封装滚动方法,接收目标偏移量
  void _scrollTo(double target) {
    // 直接用传入的控制器操作主页面滚动
    widget.scrollController.jumpTo(target);
    // 要平滑滚动的话换下面这段:
    // widget.scrollController.animateTo(
    //   target,
    //   duration: const Duration(seconds: 1),
    //   curve: Curves.easeIn,
    // );
  }

  @override
  Widget build(BuildContext context) {
    double width = MediaQuery.of(context).size.width;
    var screenSize = MediaQuery.of(context).size;

    return Container(
      color: Colors.white.withOpacity(0.5),
      child: Padding(
        padding: const EdgeInsets.all(20),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.start,
          children: [
            SizedBox(width: screenSize.width / 6),
            Image.asset("images/logo_hesap.png", width: width / 10),
            SizedBox(width: screenSize.width / 15),
            InkWell(
              onHover: (value) {
                setState(() {
                  _isHovering[0] = value;
                });
              },
              onTap: () {
                _scrollTo(4050); // 点击跳转到指定偏移量
              },
              child: Column(
                mainAxisSize: MainAxisSize.min,
                children: [
                  Text(
                    'Ana Sayfa',
                    style: TextStyle(
                      color: _isHovering[0] ? const Color(0xff000000) : const Color(0xff32b146),
                      fontWeight: FontWeight.bold,
                      fontSize: 16,
                    ),
                  ),
                  // 补全你原代码里缺失的hover下划线
                  const SizedBox(height: 5),
                  Visibility(
                    visible: _isHovering[0],
                    child: Container(height: 2, width: 20, color: Colors.black),
                  )
                ],
              ),
            ),
            // 其他按钮同理,调用_scrollTo传入不同偏移量就行
          ],
        ),
      ),
    );
  }
}

第二步:主页面传递控制器给TopBarContents

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

  @override
  State<MainPage> createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  // 主页面创建并维护滚动控制器
  final ScrollController scrollController = ScrollController();

  @override
  void dispose() {
    // 页面销毁时记得销毁控制器,避免内存泄漏
    scrollController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: PreferredSize(
        preferredSize: const Size.fromHeight(80),
        // 把主页面的控制器传给自定义AppBar
        child: TopBarContents(scrollController: scrollController),
      ),
      body: SingleChildScrollView(
        controller: scrollController,
        // 这里放你的长页面内容,示例用不同颜色容器模拟
        child: Column(
          children: [
            Container(height: 1000, color: Colors.red),
            Container(height: 1000, color: Colors.green),
            Container(height: 1000, color: Colors.blue),
            Container(height: 1000, color: Colors.yellow),
            Container(height: 1000, color: Colors.purple),
          ],
        ),
      ),
    );
  }
}

额外优化建议

如果你的页面内容是动态的,别写死固定偏移量(比如4050),用GlobalKey获取目标组件的真实位置更可靠:

// 主页面给目标组件设GlobalKey
final GlobalKey targetSectionKey = GlobalKey();

// 目标组件用上这个Key
Container(
  key: targetSectionKey,
  height: 1000,
  color: Colors.purple,
)

// TopBarContents里修改滚动方法
void _scrollToTarget() {
  RenderBox renderBox = targetSectionKey.currentContext!.findRenderObject() as RenderBox;
  Offset position = renderBox.localToGlobal(Offset.zero);
  widget.scrollController.jumpTo(position.dy);
}

内容的提问来源于stack exchange,提问作者Berkay Isıkoglu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 05:04:56