Flutter跟随引导插件follow_the_leader的使用
Flutter跟随引导插件follow_the_leader的使用
Widgets following widgets.
这个项目是Flutter Bounty Hunters的一个概念验证。想要更多的跟随功能吗?今天就来资助一个里程碑吧!
开始使用
选择一个你想要跟随的部件,并用Leader
部件包裹它。给Leader
部件一个LeaderLink
,以便与Follower
共享。
Leader(
link: _leaderLink,
child: YourLeaderWidget(),
);
添加一个你想要跟随Leader
的部件,并用Follower
部件包裹它。
// Follower 出现在 Leader 的上方20像素。
Follower.withOffset(
link: _leaderLink,
offset: const Offset(0, -20),
leaderAnchor: Alignment.topCenter,
followerAnchor: Alignment.bottomCenter,
child: YourFollowerWidget(),
);
Follower
可以使用.withOffset()
方法以固定距离跟随Leader
,如上所示。或者,Follower
可以通过使用.withAligner()
方法来精确地定位在每一帧上。
// Follower 出现在对齐器指定的位置。
Follower.withAligner(
link: _leaderLink,
aligner: _aligner,
child: YourFollowerWidget(),
);
为了限制你的Follower
出现的位置,将一个boundary
传递给你的Follower
。
// Follower 受到给定边界的约束。
Follower.withAligner(
link: _leaderLink,
aligner: _aligner,
boundary: _boundary,
child: YourFollowerWidget(),
);
构建多个不带布局的部件
在Flutter中构建跟随部件有点不同。通常,当我们构建多个部件时,我们会把它们放在一个布局容器中,比如Column
、Row
或Stack
。但是跟随部件不会遵循祖先布局规则。这就是重点。
follow_the_leader
引入了一个新的容器部件,该部件构建子部件,但不尝试应用任何特定的布局规则。此部件的主要目的是让读者明白你并不是想布局这些子部件。
BuildInOrder(
children: [
MyContentWithALeader(),
Follower.withOffset(),
Follower.withDynamics(),
],
);
BuildInOrder
部件按提供的顺序构建每个子部件。这一点很重要,因为Leader
部件必须在其Follower
之前构建。但是BuildInOrder
不会对其子部件施加任何Offset
。BuildInOrder
将其父部件的约束向下传递给children
。
示例代码
以下是完整的示例代码:
import 'package:example/demo_hover.dart';
import 'package:example/demo_interactive_viewer.dart';
import 'package:example/demo_kitchen_sink.dart';
import 'package:example/demo_page_list_viewport.dart';
import 'package:example/demo_scaling.dart';
import 'package:example/demo_scrollables.dart';
import 'package:flutter/material.dart';
import 'package:follow_the_leader/follow_the_leader.dart';
import 'package:logging/logging.dart';
import 'demo_orbiting_circles.dart';
void main() {
FtlLogs.initLoggers(Level.FINEST, {
// FtlLogs.leader,
// FtlLogs.follower,
// FtlLogs.link,
// FtlLogs.boundary,
// appLog,
});
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Follow the Leader Example',
theme: ThemeData.dark(),
debugShowCheckedModeBanner: false,
home: const ExampleApp(),
);
}
}
class ExampleApp extends StatefulWidget {
const ExampleApp({Key? key}) : super(key: key);
[@override](/user/override)
State createState() => _ExampleAppState();
}
class _ExampleAppState extends State<ExampleApp> {
final _scaffoldKey = GlobalKey<ScaffoldState>();
_MenuItem _selectedMenu = _items.first;
void _closeDrawer() {
if (_scaffoldKey.currentState!.isDrawerOpen) {
Navigator.of(context).pop();
}
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
backgroundColor: Colors.transparent,
elevation: 0,
),
extendBodyBehindAppBar: true,
body: Builder(builder: (bodyContext) {
// 使用中间的Builder,以便给页面构建器提供有限的布局边界。
return _selectedMenu.pageBuilder(bodyContext);
}),
drawer: _buildDrawer(),
);
}
Widget _buildDrawer() {
return Drawer(
child: SingleChildScrollView(
primary: false,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 48),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
for (final item in _items) ...[
_DrawerButton(
title: item.title,
onPressed: () => setState(() {
_selectedMenu = item;
_closeDrawer();
}),
isSelected: _selectedMenu == item,
),
const SizedBox(height: 24),
],
],
),
),
),
);
}
}
final _items = [
_MenuItem(
title: 'Follow the Leader',
pageBuilder: (context) => const KitchenSinkDemo(),
),
_MenuItem(
title: 'Page List Viewport',
pageBuilder: (context) => const PageListViewportDemo(),
),
_MenuItem(
title: 'Interactive Viewer',
pageBuilder: (context) => const InteractiveViewerDemo(),
),
_MenuItem(
title: 'Hover',
pageBuilder: (context) => const HoverDemo(),
),
_MenuItem(
title: 'Orbiting Circles',
pageBuilder: (context) => const OrbitingCirclesDemo(),
),
_MenuItem(
title: 'Scaling',
pageBuilder: (context) => const ScalingDemo(),
),
_MenuItem(
title: 'Scrollables',
pageBuilder: (context) => const ScrollablesDemo(),
),
];
class _DrawerButton extends StatelessWidget {
const _DrawerButton({
Key? key,
required this.title,
this.isSelected = false,
required this.onPressed,
}) : super(key: key);
final String title;
final bool isSelected;
final VoidCallback onPressed;
[@override](/user/override)
Widget build(BuildContext context) {
return SizedBox(
width: double.infinity,
child: ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateColor.resolveWith((states) {
if (isSelected) {
return const Color(0xFFBBBBBB);
}
if (states.contains(MaterialState.hovered)) {
return Colors.grey.withOpacity(0.1);
}
return Colors.transparent;
}),
foregroundColor: MaterialStateColor.resolveWith((states) => isSelected ? Colors.white : const Color(0xFFBBBBBB)),
elevation: MaterialStateProperty.resolveWith((states) => 0),
padding: MaterialStateProperty.resolveWith((states) => const EdgeInsets.all(16))),
onPressed: isSelected ? null : onPressed,
child: Center(child: Text(title)),
),
);
}
}
class _MenuItem {
const _MenuItem({
required this.title,
required this.pageBuilder,
});
final String title;
final WidgetBuilder pageBuilder;
}
更多关于Flutter跟随引导插件follow_the_leader的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter跟随引导插件follow_the_leader的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
follow_the_leader
是一个用于在 Flutter 应用中实现引导效果的插件,通常用于创建带有箭头或提示框的引导流程,帮助用户了解应用的使用方法。以下是如何使用 follow_the_leader
插件的基本指南:
1. 添加依赖
首先,在 pubspec.yaml
文件中添加 follow_the_leader
插件的依赖:
dependencies:
flutter:
sdk: flutter
follow_the_leader: ^0.4.0 # 请使用最新版本
然后运行 flutter pub get
来安装依赖。
2. 基本用法
follow_the_leader
的核心组件是 FollowTheLeader
,它可以将一个 Leader
(引导源)和一个 Follower
(跟随者)关联起来,使得 Follower
能够跟随 Leader
的位置。
import 'package:flutter/material.dart';
import 'package:follow_the_leader/follow_the_leader.dart';
class MyGuidePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Follow The Leader Example'),
),
body: Center(
child: FollowTheLeader(
leader: _buildLeader(),
follower: _buildFollower(),
),
),
);
}
Widget _buildLeader() {
return Container(
width: 100,
height: 100,
color: Colors.blue,
child: Center(
child: Text(
'Leader',
style: TextStyle(color: Colors.white),
),
),
);
}
Widget _buildFollower() {
return Container(
width: 50,
height: 50,
decoration: BoxDecoration(
color: Colors.red,
shape: BoxShape.circle,
),
child: Center(
child: Text(
'F',
style: TextStyle(color: Colors.white),
),
),
);
}
}
3. 高级用法
FollowTheLeader
组件提供了多种配置选项,例如调整 Follower
的位置、动画效果等。
FollowTheLeader(
leader: _buildLeader(),
follower: _buildFollower(),
offset: Offset(0, 50), // Follower 相对于 Leader 的偏移量
delay: Duration(milliseconds: 500), // 延迟时间
curve: Curves.easeInOut, // 动画曲线
)
4. 在引导流程中使用
可以将 FollowTheLeader
用于引导流程中,例如在用户首次打开应用时显示引导提示。
class GuidedApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Guided App'),
),
body: Column(
children: [
FollowTheLeader(
leader: _buildLeader(),
follower: _buildFollower(),
),
ElevatedButton(
onPressed: () {
// 下一步引导
},
child: Text('Next'),
),
],
),
),
);
}
}
5. 自定义引导内容
Follower
可以是任何 Widget
,因此你可以自定义引导提示的内容和样式。
Widget _buildFollower() {
return Container(
padding: EdgeInsets.all(8),
decoration: BoxDecoration(
color: Colors.green,
borderRadius: BorderRadius.circular(8),
),
child: Text(
'This is a helpful tip!',
style: TextStyle(color: Colors.white),
),
);
}
6. 处理引导结束
当用户完成引导时,可以通过回调函数来处理引导结束的逻辑。
FollowTheLeader(
leader: _buildLeader(),
follower: _buildFollower(),
onCompleted: () {
// 引导完成后的操作
print('Guide completed!');
},
)