我正在尝试找到一种方法来单击导航栏中的元素并使页面自动向下滚动到该部分。我的一页网站由 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;
});
},
最佳答案
更新:
我通过对你的代码进行一点更改解决了这个问题并为我工作:)
我使用 ValueNotifier
和 ValueLisenableBuilder
来传输值,并使用 ValueChanged
将值传递到菜单小部件外部。
但更好的是,建议使用一名状态管理器来完成这项工作。
对于切换滚动可以使用 GlobalKey
和 Scrollable.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));
});
},
),
),
),
),
);
}
}
关于flutter - 如何通过 flutter 中的导航栏为单页 Web 应用程序实现动态滚动?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75276706/