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

如何用Flutter构建带跳转功能的顶部导航单页网站?能否无需第三方包?

用Flutter实现单页内导航的网站:可行方案及无第三方包实现方式

完全可以用Flutter实现这类单页网站,Flutter Web对这种锚点式内导航的场景支持很好,而且不需要依赖任何第三方包,用框架自带的API就能搞定。

核心实现思路

利用Flutter的ScrollController控制滚动行为,配合GlobalKey标记页面内的各个目标区域,点击导航栏选项时,触发滚动到对应区域的位置。

无第三方包的具体实现代码

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '单页内导航示例',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const SinglePageSite(),
    );
  }
}

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

  @override
  State<SinglePageSite> createState() => _SinglePageSiteState();
}

class _SinglePageSiteState extends State<SinglePageSite> {
  // 控制页面滚动的控制器
  final ScrollController _scrollController = ScrollController();
  // 标记各个内容区域的GlobalKey
  final GlobalKey _homeKey = GlobalKey();
  final GlobalKey _aboutKey = GlobalKey();
  final GlobalKey _projectsKey = GlobalKey();
  final GlobalKey _contactKey = GlobalKey();

  // 滚动到指定区域的方法
  void _scrollToSection(GlobalKey key) {
    final RenderObject? renderObject = key.currentContext?.findRenderObject();
    if (renderObject != null) {
      final RenderBox renderBox = renderObject as RenderBox;
      final Offset offset = renderBox.localToGlobal(Offset.zero);
      _scrollController.animateTo(
        offset.dy,
        duration: const Duration(milliseconds: 500),
        curve: Curves.easeInOut,
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('我的单页网站'),
        actions: [
          TextButton(
            onPressed: () => _scrollToSection(_homeKey),
            child: const Text('首页', style: TextStyle(color: Colors.white)),
          ),
          TextButton(
            onPressed: () => _scrollToSection(_aboutKey),
            child: const Text('关于我', style: TextStyle(color: Colors.white)),
          ),
          TextButton(
            onPressed: () => _scrollToSection(_projectsKey),
            child: const Text('项目', style: TextStyle(color: Colors.white)),
          ),
          TextButton(
            onPressed: () => _scrollToSection(_contactKey),
            child: const Text('联系我', style: TextStyle(color: Colors.white)),
          ),
        ],
      ),
      body: SingleChildScrollView(
        controller: _scrollController,
        child: Column(
          children: [
            // 首页区域
            Container(
              key: _homeKey,
              height: MediaQuery.of(context).size.height,
              color: Colors.lightBlue,
              child: const Center(child: Text('首页内容', style: TextStyle(fontSize: 24))),
            ),
            // 关于我区域
            Container(
              key: _aboutKey,
              height: MediaQuery.of(context).size.height,
              color: Colors.lightGreen,
              child: const Center(child: Text('关于我内容', style: TextStyle(fontSize: 24))),
            ),
            // 项目区域
            Container(
              key: _projectsKey,
              height: MediaQuery.of(context).size.height,
              color: Colors.orange,
              child: const Center(child: Text('项目内容', style: TextStyle(fontSize: 24))),
            ),
            // 联系我区域
            Container(
              key: _contactKey,
              height: MediaQuery.of(context).size.height,
              color: Colors.purple,
              child: const Center(child: Text('联系我内容', style: TextStyle(fontSize: 24))),
            ),
          ],
        ),
      ),
    );
  }

  @override
  void dispose() {
    _scrollController.dispose();
    super.dispose();
  }
}

关键代码说明

  • ScrollController:负责管理页面的滚动状态,调用animateTo方法实现平滑滚动效果。
  • GlobalKey:用来定位每个内容区域的位置,通过currentContext获取对应区域的渲染对象,进而计算出滚动目标偏移量。
  • animateTo方法:参数中的duration控制滚动动画时长,curve定义动画曲线,可根据需求调整。

额外优化点

  • 可以给导航项添加选中状态,通过监听ScrollController的滚动位置,判断当前显示的区域,高亮对应的导航按钮。
  • 针对Web端,可以处理浏览器的前进/后退按钮,通过监听路由变化同步滚动位置,这部分也可以用Flutter自带的RouteObserver实现。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 01:03:36