flutter - 如何通过 flutter 中的导航栏为单页 Web 应用程序实现动态滚动?

标签 flutter dart scroll navbar

我正在尝试找到一种方法来单击导航栏中的元素并使页面自动向下滚动到该部分。我的一页网站由 SingleChildScrollView 组成,其中不同的部分(例如,关于、服务、联系我们……)作为该 ScrollView 的子项。这个结构是在我的 HomeScreen 类中编写的。导航栏位于不同的 dart 文件中并生成。我怎样才能使这些相互链接。 GIF:/image/VkM2W.jpg

主屏幕类(在 main.dart 中启动)

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SingleChildScrollView(
        child: Column(
          children: [
            TopSection(),
            SizedBox(height: kDefaultPadding * 2),
            AboutSection(),
            ServiceSection(),
            TestimonialSection(),
            SizedBox(height: kDefaultPadding),
            ContactSection(),
            SizedBox(height: 50)
          ],
        ),
      ),
    );
  }
}

您可以点击导航栏中的元素的部分

class _MenuState extends State<Menu> {
  int selectedIndex = 0;
  int hoverIndex = 0;
  List<String> menuItems = [
    "Home",
    "About",
    "Services",
    "Testimonials",
    "Contact"
  ];
  @override
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.symmetric(horizontal: kDefaultPadding * 2.5),
      constraints: BoxConstraints(maxWidth: 1110),
      height: 100,
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.only(
          topLeft: Radius.circular(10),
          topRight: Radius.circular(10),
        ),
        boxShadow: [kDefaultShadow],
      ),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: List.generate(
          menuItems.length,
          (index) => buildMenuItem(index),
        ),
      ),
    );
  }

  Widget buildMenuItem(int index) => InkWell(
        onTap: () {
          setState(() {
            selectedIndex = index;
          });
        },

各部分下方的导航栏示例 navbar

最佳答案

更新:

我通过对你的代码进行一点更改解决了这个问题并为我工作:) 我使用 ValueNotifierValueLisenableBuilder 来传输值,并使用 ValueChanged 将值传递到菜单小部件外部。 但更好的是,建议使用一名状态管理器来完成这项工作。 对于切换滚动可以使用 GlobalKey Scrollable.ensureVisibleenter image description here

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: HomeScreen(),
    );
  }
}

class HomeScreen extends StatefulWidget {
  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  late ValueNotifier<int> notifier;
  final List<GlobalKey> itemKeys = [
    GlobalKey(),
    GlobalKey(),
    GlobalKey(),
    GlobalKey(),
    GlobalKey()
  ];

  @override
  void initState() {
    notifier = ValueNotifier(0);
    super.initState();
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SingleChildScrollView(
          child: ValueListenableBuilder<int>(
        valueListenable: notifier,
        builder: (context, val, widget) {
          return Column(children: [
            Menu(
              valueChanged: (int value) {
                print("$value");
                notifier.value = value;
                notifier.notifyListeners();
                Scrollable.ensureVisible(itemKeys[value].currentContext!,
                    duration: Duration(seconds: 1),
                    // duration for scrolling time
                    alignment: .5,
                    // 0 mean, scroll to the top, 0.5 mean, half
                    curve: Curves.easeInOutCubic);
              },
            ),
            Item(title: "Home", key: itemKeys[0]),
            Item(title: "About", key: itemKeys[1]),
            Item(title: "Services", key: itemKeys[2]),
            Item(title: "Testimonials", key: itemKeys[3]),
            Item(title: "Contact", key: itemKeys[4]),
          ]);
        },
      )),
    );
  }
}

class Item extends StatelessWidget {
  const Item({Key? key, required this.title}) : super(key: key);
  final String title;

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 400,
      width: double.infinity,
      color: Colors.deepPurpleAccent,
      child: Text("$title"),
    );
  }
}

class Menu extends StatefulWidget {
  Menu({Key? key, required this.valueChanged}) : super(key: key);
  ValueChanged<int> valueChanged;

  @override
  State<Menu> createState() => _MenuState();
}

class _MenuState extends State<Menu> {
  int selectedIndex = 0;
  int hoverIndex = 0;
  List<String> menuItems = [
    "Home",
    "About",
    "Services",
    "Testimonials",
    "Contact"
  ];

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.symmetric(horizontal: 70 * 2.5),
      constraints: BoxConstraints(maxWidth: 1110),
      height: 100,
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.only(
          topLeft: Radius.circular(10),
          topRight: Radius.circular(10),
        ),
      ),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: List.generate(
          menuItems.length,
          (index) => Container(
            color: selectedIndex == index ? Colors.red : Colors.green,
            width: 100,
            height: 100,
            child: InkWell(
              child: Text("${menuItems[index]}"),
              onTap: () {
                setState(() {
                  selectedIndex = index;
                  widget.valueChanged((index));
                });
              },
            ),
          ),
        ),
      ),
    );
  }
}

关于flutter - 如何通过 flutter 中的导航栏为单页 Web 应用程序实现动态滚动?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75276706/

相关文章:

flutter - 如何使用 Dio 包在 Flutter 中的 formdata 中发送数组?

flutter - 有谁知道如何使用 flutter 实现带有类似于 instagram 的选项卡的搜索栏?

Flutter:如何将 Excel 电子表格中的粘贴列值直接复制到我的 Flutter UI 中?

firebase - 如何基于uid创建用户个人资料并导航到个人资料页面?

flutter - 如何在Dart/Flutter中将某些元素从一个Map复制到新Map中?

javascript - 粘性导航栏在粘性后更改 CSS

html - 对 Angular 线溢出滚动不适用于 chrome 或 opera

database - 如何在 flutter 中从插入到 sqflite 数据库中返回 id

dart - getter 'length' 在 null 上被调用

javascript - Firefox 不需要的滚动