Flutter锚点定位插件flutter_anchorlable的使用
Flutter锚点定位插件flutter_anchorlable的使用
flutter_anchorlable
是一个用于Flutter的插件,它提供了可自由滚动的小部件及其控制器,并以键作为锚点。通过这个插件,你可以轻松实现页面内滚动到指定位置的功能。
安装
在你的Flutter项目的pubspec.yaml
文件中添加以下依赖:
dependencies:
flutter_anchorlable: <latest_version>
然后,在你的库中添加以下导入:
import 'package:flutter_anchorlable/flutter_anchorlable.dart';
使用
创建控制器
AnchorlableController
是一个控制器,它允许你滚动由附加客户端拥有的小部件。通过指定 initialAnchorKey
,可以指定附加客户端的初始滚动位置。
final controller = AnchorlableController();
跳转到指定锚点
jumpToAnchor
方法可以让页面直接跳转到指定的锚点。
controller.jumpToAnchor(anchorKey);
动画滚动到指定锚点
animateToAnchor
方法可以为带有目标键的小部件执行动画滚动。如果你不确定选择哪种曲线(Curve),可以参考 Flutter官方文档。
onPressed: () async {
await controller.animateToAnchor(anchor,
duration: const Duration(seconds: 1),
curve: Curves.fastOutSlowIn);
}
垂直排列小部件
AnchorlableScrollColumn
可以用来垂直排列小部件。它需要一个 Key
和 AnchorlableController
。通过使用 AnchorlableController
,可以滚动带有 Key
的小部件。
final controller = AnchorlableController();
const anchorKey = GlobalObjectKey('anchor');
AnchorlableScrollColumn(
controller: controller,
children: [
Container(
child: Text(
key: anchorKey,
'Widgets you want to anchor',
),
),
// 其他子组件
],
);
水平排列小部件
AnchorlableScrollRow
是 AnchorlableScrollColumn
的横向版本。
final controller = AnchorlableController();
const anchorKey = GlobalObjectKey('anchor');
AnchorlableScrollRow(
controller: controller,
children: [
Container(
child: Text(
key: anchorKey,
'Widgets you want to anchor',
),
),
// 其他子组件
],
);
与 CustomScrollView
配合使用
AnchorlableSliverColumn
是一个可以与 CustomScrollView
一起使用的锚点小部件。与 AnchorlableScrollColumn
不同,它需要一些额外的工作来处理 AnchorlableController
。
final controller = AnchorlableController();
const anchorKey = GlobalObjectKey('anchor');
CustomScrollView(
controller: controller,
slivers: [
AnchorlableSliverColumn(
children: [
Container(
child: Text(
key: anchorKey,
'Widgets you want to anchor',
),
),
// 其他子组件
],
),
],
);
AnchorlableSliverRow
是 AnchorlableSliverColumn
的横向版本。
示例代码
下面是一个完整的示例,展示了如何使用 flutter_anchorlable
实现一个简单的个人作品集网站:
import 'package:flutter/material.dart';
import 'package:flutter_anchorlable/flutter_anchorlable.dart';
import 'package:url_launcher/url_launcher.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: "Hiyoko's Portfolio",
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
final anchorlableBodyController = AnchorlableController();
Widget animateJumpButton(String data, GlobalKey anchor) => TextButton(
onPressed: () async {
await anchorlableBodyController.animateToAnchor(anchor,
duration: const Duration(seconds: 1),
curve: Curves.fastOutSlowIn);
},
child: Text(
data,
style: const TextStyle(fontSize: 30, color: Colors.black),
),
);
Widget Footer() {
return Container(
height: 100,
width: MediaQuery.of(context).size.width,
key: contactKey,
alignment: Alignment.bottomLeft,
color: Colors.black,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text(
'Contact Me',
style: TextStyle(color: Colors.white, fontSize: 32),
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
IconButton(
iconSize: 50,
icon: const Icon(Icons.web, color: Colors.white),
onPressed: () async {
await launchUrl(Uri.parse('https://zenn.dev/antman'));
},
),
IconButton(
iconSize: 50,
icon: const Icon(Icons.github, color: Colors.white),
onPressed: () async {
await launchUrl(Uri.parse('https://github.com/yama-yeah'));
},
),
],
),
],
),
);
}
Widget Header() {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text("Hiyoko's Portfolio", style: TextStyle(fontSize: 32)),
Padding(
padding: const EdgeInsets.only(right: 40),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
animateJumpButton('works', worksKey),
animateJumpButton('Intro', introKey),
animateJumpButton('Contact', contactKey),
],
),
),
],
);
}
Widget work(String data, String imageUrl, String url) => TextButton(
onPressed: () async => await launchUrl(Uri.parse(url)),
child: Column(
children: [
Text(data, style: const TextStyle(fontSize: 48)),
Image.network(
imageUrl,
width: 400,
),
],
),
);
return Scaffold(
body: AnchorlableScrollColumn(
shrinkWrap: true,
controller: anchorlableBodyController,
children: [
Header(),
const SizedBox(height: 60),
const Text(
key: introKey,
'Hello My name is Hiyoko!!!',
style: TextStyle(fontSize: 32),
),
const Text(
'I like a Humbugger!!!',
style: TextStyle(fontSize: 32),
),
const Text(
'Welcome to my site',
style: TextStyle(fontSize: 32),
),
const SizedBox(height: 60),
SizedBox(
height: 1100,
child: Column(
key: worksKey,
children: [
const Text(
'There are My Works',
style: TextStyle(fontSize: 32),
),
Row(
children: [
work(
'Maho',
'https://user-images.githubusercontent.com/82094614/190878311-8049c43e-360f-449c-85d2-3958aa5754f.png',
'https://github.com/yama-yeah/Maho',
),
work(
'glassmorphism_widget',
'https://user-images.githubusercontent.com/82094614/147371522-76db6662-3945-4470-bad3-1dfec306ccd1.png',
'https://github.com/yama-yeah/glassmorphism_widgets',
),
work(
'flutter_anchorlable',
'https://user-images.githubusercontent.com/82094614/190932053-f3228df0-d264-4427-a17b-bce43f130fa7.gif',
'https://github.com/yama-yeah/flutter_anchorlable',
),
],
),
],
),
),
const SizedBox(height: 60),
Footer(),
],
),
);
}
}
final anchorlableBodyController = AnchorlableController();
const introKey = GlobalObjectKey('intro');
const worksKey = GlobalObjectKey('works');
const contactKey = GlobalObjectKey('contact');
更多关于Flutter锚点定位插件flutter_anchorlable的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter锚点定位插件flutter_anchorlable的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何使用 flutter_anchorable
插件在 Flutter 中实现锚点定位的示例代码。这个插件允许你在滚动视图中定位到特定的锚点。
首先,确保你已经在 pubspec.yaml
文件中添加了 flutter_anchorable
依赖:
dependencies:
flutter:
sdk: flutter
flutter_anchorable: ^x.y.z # 请替换为最新版本号
然后,运行 flutter pub get
来获取依赖。
以下是一个简单的示例,展示如何使用 flutter_anchorable
插件:
import 'package:flutter/material.dart';
import 'package:flutter_anchorable/flutter_anchorable.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Anchorable Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(
title: Text('Flutter Anchorable Demo'),
),
body: AnchorableListViewDemo(),
),
);
}
}
class AnchorableListViewDemo extends StatefulWidget {
@override
_AnchorableListViewDemoState createState() => _AnchorableListViewDemoState();
}
class _AnchorableListViewDemoState extends State<AnchorableListViewDemo> {
final List<String> items = List.generate(100, (index) => "Item $index");
AnchorableController? _anchorableController;
@override
void initState() {
super.initState();
_anchorableController = AnchorableController();
// 自动滚动到第50项
Future.delayed(Duration.zero, () {
_anchorableController?.scrollToAnchor("item-50");
});
}
@override
void dispose() {
_anchorableController?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: AnchorableListView(
controller: _anchorableController,
children: List.generate(items.length, (index) {
return Anchorable(
key: ValueKey("item-$index"),
anchorId: "item-$index",
child: ListTile(
title: Text(items[index]),
),
);
}),
),
);
}
}
代码解释:
-
依赖添加:确保在
pubspec.yaml
中添加了flutter_anchorable
依赖。 -
AnchorableListViewDemo:创建了一个包含 100 个项目的列表视图。
-
AnchorableController:初始化
AnchorableController
来控制锚点滚动。 -
Auto Scroll:在
initState
中,使用Future.delayed(Duration.zero, ...)
来立即(在下一个事件循环中)滚动到第 50 项。这模拟了页面加载后自动滚动到特定位置的效果。 -
AnchorableListView:使用
AnchorableListView
包装列表,并通过Anchorable
包装每个列表项,设置唯一的anchorId
。 -
滚动到锚点:通过
_anchorableController?.scrollToAnchor("item-50")
方法滚动到指定的锚点。
注意事项:
- 确保每个
Anchorable
的anchorId
是唯一的。 - 可以在用户交互(如按钮点击)时调用
scrollToAnchor
方法来实现动态滚动。
这个示例展示了如何使用 flutter_anchorable
插件在 Flutter 应用中实现锚点定位功能。你可以根据需要进一步定制和扩展这个示例。