Flutter滚动动画插件flutter_scroll_animation的使用
Flutter滚动动画插件flutter_scroll_animation的使用
flutter_scroll_animation 是一个为 Flutter 提供滚动驱动动画的包。当小部件进入视口时,它们会变得可见并以自定义滑动和淡入效果进行动画展示,从而实现流畅且动态的用户界面过渡。
特性
- 检测小部件何时进入视口,并使用可定制的滑动和淡入效果对其进行动画处理。
- 新增了缩放、旋转和循环动画功能。
- 可设置触发动画的可见性阈值。
- 支持延迟动画,用于创建交错效果。
- 高度灵活,易于集成到任何 Flutter 应用程序中。
- 可自定义动画持续时间、方向、曲线以及退出行为。
开始使用
要使用此包,请将其添加到您的 pubspec.yaml 文件中:
dependencies:
flutter_scroll_animation: ^0.0.1
然后运行以下命令来获取依赖项:
flutter pub get
使用示例
以下是一个简单的示例,演示如何在应用程序中使用 ScrollAnimationWidget:
import 'package:flutter/material.dart';
import 'package:flutter_scroll_animation/flutter_scroll_animation.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Scroll Animation Example',
theme: ThemeData(primarySwatch: Colors.blue),
home: const ExampleScreen(),
);
}
}
class ExampleScreen extends StatelessWidget {
const ExampleScreen({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Scroll Animation Example')),
body: ListView.builder(
itemCount: 20,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(16.0),
child: ScrollAnimationWidget(
index: 'item_$index',
alignment: index.isEven ? Alignment.centerRight : Alignment.centerLeft,
child: Card(
child: ListTile(
title: Text('Item $index'),
),
),
),
);
},
),
);
}
}
说明:
ScrollAnimationWidget是该包的核心组件,用于实现滚动驱动动画。- 参数
index用于唯一标识每个动画小部件。 alignment控制小部件的对齐方式(如左对齐或右对齐)。child是需要动画的小部件。
自定义动画
可以通过传递参数来自定义动画的持续时间、曲线等属性。以下是一些自定义示例:
自定义持续时间和曲线
ScrollAnimationWidget(
index: 'item_1',
alignment: Alignment.centerLeft,
duration: Duration(milliseconds: 700),
curve: Curves.easeInOut,
child: YourWidget(),
)
启用缩放和旋转动画
ScrollAnimationWidget(
index: 'scale_icon',
alignment: Alignment.center,
enableScale: true, // 启用缩放动画
enableRotation: true, // 启用旋转动画
duration: Duration(milliseconds: 800),
child: Icon(Icons.star, size: 50, color: Colors.amber),
)
循环动画
ScrollAnimationWidget(
index: 'looping_text',
alignment: Alignment.centerLeft,
loopAnimation: true, // 循环动画
alternate: true, // 前后交替
duration: Duration(seconds: 2),
child: Text('Looping Animation'),
)
延迟动画
ScrollAnimationWidget(
index: 'delayed_button',
alignment: Alignment.centerLeft,
delay: Duration(milliseconds: 500), // 延迟 500 毫秒
child: ElevatedButton(
onPressed: () {},
child: Text('Delayed Animation'),
),
)
自定义可见性阈值
ScrollAnimationWidget(
index: 'custom_visibility',
alignment: Alignment.centerLeft,
visibilityThreshold: 0.5, // 当 50% 可见时触发动画
duration: Duration(milliseconds: 600),
child: Container(
width: 150,
height: 150,
color: Colors.blue,
child: Center(child: Text('50% Visible')),
),
)
高级自定义选项
该包提供了许多高级选项:
退出时反转动画
ScrollAnimationWidget(
index: 'advanced_example',
alignment: Alignment.center,
reverseOnExit: true, // 动画退出时反转
enableFade: true, // 启用淡入淡出
resetOnScroll: true, // 滚动时重置动画
onAnimationStart: () => print('Animation started!'), // 动画开始回调
onAnimationEnd: () => print('Animation ended!'), // 动画结束回调
child: Text('Advanced Scroll Animation'),
)
示例完整代码
以下是一个完整的示例代码,展示了上述所有功能:
import 'package:flutter/material.dart';
import 'package:flutter_scroll_animation/flutter_scroll_animation.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Scroll Animation Demo',
theme: ThemeData(primarySwatch: Colors.blue),
home: const ExampleScreen(),
);
}
}
class ExampleScreen extends StatelessWidget {
const ExampleScreen({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Scroll Animation Demo')),
body: ListView(
physics: const AlwaysScrollableScrollPhysics(),
children: [
const SectionTitle(title: "Enhanced Card Animations"),
buildEnhancedAnimatedCards(),
const SectionTitle(title: "Scale & Rotation Animations"),
buildScaleAndRotationIcons(),
const SectionTitle(title: "Looping Text Animations"),
buildLoopingText(),
const SectionTitle(title: "Delayed Animations"),
buildDelayedButtons(),
const SectionTitle(title: "Custom Visibility Thresholds with Containers"),
buildCustomVisibilityContainers(),
// 添加底部空间以确保完全滚动
const SizedBox(height: 400),
],
),
);
}
// 展示增强的卡片动画
Widget buildEnhancedAnimatedCards() {
return Column(
children: List.generate(4, (index) {
return Padding(
padding: const EdgeInsets.all(16.0),
child: ScrollAnimationWidget(
index: 'enhanced_card_$index',
alignment: index.isEven ? Alignment.centerRight : Alignment.centerLeft,
duration: const Duration(milliseconds: 800),
curve: Curves.easeInOutCubic,
reverseOnExit: true, // 退出时反转动画
enableScale: true, // 启用缩放
child: Card(
elevation: 4,
child: ListTile(
title: Text('Enhanced Card $index'),
subtitle: const Text('This card has enhanced animations.'),
),
),
),
);
}),
);
}
// 展示缩放和旋转动画
Widget buildScaleAndRotationIcons() {
return Column(
children: [
ScrollAnimationWidget(
index: 'scale_icon',
alignment: Alignment.center,
enableScale: true, // 启用缩放动画
duration: const Duration(milliseconds: 800),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Icon(Icons.stars, size: 50, color: Colors.purple),
),
),
ScrollAnimationWidget(
index: 'rotation_icon',
alignment: Alignment.center,
enableRotation: true, // 启用旋转动画
duration: const Duration(milliseconds: 800),
curve: Curves.elasticInOut,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Icon(Icons.rotate_right, size: 50, color: Colors.orange),
),
),
],
);
}
// 展示循环动画
Widget buildLoopingText() {
return Column(
children: [
ScrollAnimationWidget(
index: 'looping_text_1',
alignment: Alignment.centerLeft,
loopAnimation: true, // 循环动画
duration: const Duration(seconds: 2),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: const Text(
'This text loops continuously.',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
),
),
ScrollAnimationWidget(
index: 'looping_text_2',
alignment: Alignment.centerRight,
loopAnimation: true,
alternate: true, // 前后交替
duration: const Duration(seconds: 2),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: const Text(
'This text alternates between forward and reverse.',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
),
),
],
);
}
// 展示延迟动画
Widget buildDelayedButtons() {
return Column(
children: [
ScrollAnimationWidget(
index: 'delayed_button_1',
alignment: Alignment.centerLeft,
duration: const Duration(milliseconds: 600),
delay: const Duration(milliseconds: 200), // 延迟 200 毫秒
child: Padding(
padding: const EdgeInsets.all(16.0),
child: ElevatedButton(
onPressed: () {},
child: const Text('Button with 200ms delay'),
),
),
),
ScrollAnimationWidget(
index: 'delayed_button_2',
alignment: Alignment.centerRight,
duration: const Duration(milliseconds: 600),
delay: const Duration(milliseconds: 500), // 延迟 500 毫秒
child: Padding(
padding: const EdgeInsets.all(16.0),
child: ElevatedButton(
onPressed: () {},
child: const Text('Button with 500ms delay'),
),
),
),
],
);
}
// 展示自定义可见性阈值
Widget buildCustomVisibilityContainers() {
return Column(
children: [
ScrollAnimationWidget(
index: 'visibility_custom_container_1',
alignment: Alignment.centerLeft,
visibilityThreshold: 0.5, // 当 50% 可见时触发
duration: const Duration(milliseconds: 600),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Container(
width: 150,
height: 150,
color: Colors.blue,
child: Stack(
children: [
Positioned(
top: 75, // 50% 高度
left: 0,
right: 0,
child: CustomPaint(
painter: DashedLinePainter(),
child: SizedBox(height: 1),
),
),
const Center(
child: Text(
'50% Visible',
style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
),
),
],
),
),
),
),
ScrollAnimationWidget(
index: 'visibility_custom_container_2',
alignment: Alignment.centerRight,
visibilityThreshold: 0.1, // 当 10% 可见时触发
duration: const Duration(milliseconds: 600),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Container(
width: 150,
height: 150,
color: Colors.red,
child: Stack(
children: [
Positioned(
top: 15, // 10% 高度
left: 0,
right: 0,
child: CustomPaint(
painter: DashedLinePainter(),
child: SizedBox(height: 1),
),
),
const Center(
child: Text(
'10% Visible',
style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
),
),
],
),
),
),
),
],
);
}
}
class SectionTitle extends StatelessWidget {
final String title;
const SectionTitle({required this.title, super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 20.0),
child: Text(
title,
style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
),
);
}
}
class DashedLinePainter extends CustomPainter {
final Color color;
final double dashWidth;
final double dashSpace;
final Axis direction;
DashedLinePainter({
this.color = Colors.black,
this.dashWidth = 5.0,
this.dashSpace = 3.0,
this.direction = Axis.horizontal,
});
[@override](/user/override)
void paint(Canvas canvas, Size size) {
final paint = Paint()
..color = color
..strokeWidth = 2.0;
double startX = 0.0;
double startY = 0.0;
if (direction == Axis.horizontal) {
while (startX < size.width) {
canvas.drawLine(Offset(startX, 0.0), Offset(startX + dashWidth, 0.0), paint);
startX += dashWidth + dashSpace;
}
} else {
while (startY < size.height) {
canvas.drawLine(Offset(0.0, startY), Offset(0.0, startY + dashWidth), paint);
startY += dashWidth + dashSpace;
}
}
}
[@override](/user/override)
bool shouldRepaint(CustomPainter oldDelegate) {
return false;
}
}
更多关于Flutter滚动动画插件flutter_scroll_animation的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter滚动动画插件flutter_scroll_animation的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
flutter_scroll_animation 是一个用于在 Flutter 中实现滚动动画的插件。它可以帮助你在用户滚动页面时,为某些元素添加动画效果。虽然 flutter_scroll_animation 并不是 Flutter 官方提供的插件,但它提供了一种简单的方式来创建基于滚动的动画。
安装插件
首先,你需要在 pubspec.yaml 文件中添加 flutter_scroll_animation 插件的依赖:
dependencies:
flutter:
sdk: flutter
flutter_scroll_animation: ^1.0.0 # 请使用最新版本
然后运行 flutter pub get 来安装插件。
使用 flutter_scroll_animation
以下是一个简单的示例,展示如何使用 flutter_scroll_animation 插件来实现基于滚动的动画。
import 'package:flutter/material.dart';
import 'package:flutter_scroll_animation/flutter_scroll_animation.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Scroll Animation Example'),
),
body: ScrollAnimationExample(),
),
);
}
}
class ScrollAnimationExample extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Column(
children: [
Container(
height: 200,
color: Colors.blue,
child: Center(
child: ScrollAnimation(
child: Text(
'Scroll Me!',
style: TextStyle(
color: Colors.white,
fontSize: 24,
),
),
startAnimationOffset: 100.0,
endAnimationOffset: 300.0,
animationCurve: Curves.easeInOut,
animationDuration: Duration(seconds: 1),
builder: (context, child, animation) {
return Opacity(
opacity: animation.value,
child: Transform.translate(
offset: Offset(0.0, 50.0 * (1 - animation.value)),
child: child,
),
);
},
),
),
),
Container(
height: 1000,
color: Colors.grey[300],
),
],
),
);
}
}

