繁体   English   中英

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

[英]How to implement dynamic scrolling via a navbar in flutter for a single-page web app?

我正在尝试找到一种方法来单击导航栏中的元素并让页面自动向下滚动到该部分。 我的单页网站由一个 SingleChildScrollView 组成,不同的部分(例如关于、服务、联系我们等)作为该滚动视图的子部分。 这个结构写在我的主屏幕 class 中。导航栏在不同的 dart 文件中并生成。 我怎样才能使它们相互链接。 GIF: https://imgur.com/a/pukCfao

主屏幕 class(在 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;
          });
        },

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

更新:

我通过稍微更改您的代码并为我工作解决了这个问题:)我使用ValueNotifierValueLisenableBuilder来传输值并使用ValueChanged来将值传递到菜单小部件外部。 但更好,建议使用一位 state 经理来完成这项工作。 对于开关滚动可以使用GlobalKeyScrollable.ensureVisible 在此处输入图像描述

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));
                });
              },
            ),
          ),
        ),
      ),
    );
  }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM