Flutter滚动动画插件scroll_animator的使用

发布于 1周前 作者 zlyuanteng 来自 Flutter

Flutter滚动动画插件 scroll_animator 的使用

scroll_animator 是一个提供平滑、动画滚动效果的 Flutter 插件,适用于鼠标滚轮、触控板、键盘以及编程方式的滚动操作。它包含了一些常用的滚动动画可以直接使用,并且也提供了灵活性来实现自定义的滚动动画。

功能演示

以下是一个示例应用程序,展示了该插件提供的功能:

示例代码

import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:scroll_animator/scroll_animator.dart';

void main() => runApp(const ExampleApp());

class ExampleApp extends StatelessWidget {
  const ExampleApp({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) => MaterialApp(
    // 自定义快捷键
    shortcuts: {
      ...WidgetsApp.defaultShortcuts,
      const SingleActivator(LogicalKeyboardKey.keyW): const ScrollIntent(direction: AxisDirection.up),
      const SingleActivator(LogicalKeyboardKey.keyS): const ScrollIntent(direction: AxisDirection.down),
      const SingleActivator(LogicalKeyboardKey.keyA): const ScrollIntent(direction: AxisDirection.left),
      const SingleActivator(LogicalKeyboardKey.keyD): const ScrollIntent(direction: AxisDirection.right),
    },

    // 使用 AnimatedScrollAction 替换默认的 ScrollAction
    actions: {
      ...WidgetsApp.defaultActions,
      ScrollIntent: AnimatedScrollAction(),
    },

    home: AnimatedPrimaryScrollController(
      animationFactory: const ChromiumEaseInOut(),
      child: Builder(
        builder: (context) => Scaffold(
          appBar: AppBar(title: const Text('Scroll Animator Example')),

          // 浮动按钮用于随机滚动到指定位置
          floatingActionButton: FloatingActionButton(
            child: const Icon(Icons.question_mark),
            onPressed: () {
              final scrollController = PrimaryScrollController.of(context);
              final offset = lerpDouble(
                scrollController.position.minScrollExtent,
                scrollController.position.maxScrollExtent,
                Random().nextDouble(),
              );
              if (scrollController is AnimatedScrollController) {
                scrollController.animateTo(offset ?? 0.0);
              } else {
                scrollController.animateTo(
                  offset ?? 0.0,
                  duration: const Duration(milliseconds: 500),
                  curve: Curves.easeInOut,
                );
              }
            },
          ),

          // 包含 ListView 的 Focus 组件
          body: Focus(
            autofocus: true,
            child: ListView.builder(
              itemCount: 100,
              itemBuilder: (context, index) => ListTile(
                title: Text('Item $index'),
              ),
            ),
          ),
        ),
      ),
    ),
  );
}

滚动动画

该插件提供了两种内置的 ScrollAnimation 实现,直接从 Chromium 移植过来,并带有单元测试,确保它们在行为上与基于 Chromium 的浏览器完全相同。

ChromiumEaseInOut

这是大多数基于 Chromium 的浏览器的默认滚动动画,在启用 #smooth-scrolling 标志并禁用 #windows-scrolling-personality 标志时生效。

ChromiumImpulse

这是 Microsoft Edge 的默认滚动动画,也可以通过启用 #smooth-scrolling#windows-scrolling-personality 标志在其他基于 Chromium 的浏览器中启用。

指针精度

触控板通常提供精确且频繁的滚动增量,但这并不意味着不需要平滑滚动。有些触控板会产生较大且不频繁的增量,类似于鼠标滚轮。因此,该插件处理所有滚动输入时不假设指针类型。

完整示例 Demo

下面是一个更完整的示例,展示了如何使用 scroll_animator 插件来创建一个具有平滑滚动效果的应用程序:

import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:scroll_animator/scroll_animator.dart';

void main() => runApp(const ExampleApp());

class ExampleApp extends StatelessWidget {
  const ExampleApp({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) => MaterialApp(
    home: Scaffold(
      appBar: AppBar(title: const Text('Scroll Animator Example')),
      body: _ScrollAnimatorExample(),
    ),
  );
}

class _ScrollAnimatorExample extends StatefulWidget {
  [@override](/user/override)
  _ScrollAnimatorExampleState createState() => _ScrollAnimatorExampleState();
}

class _ScrollAnimatorExampleState extends State<_ScrollAnimatorExample> {
  late final DateTime _startDateTime;
  late final ScrollController _scrollController;

  [@override](/user/override)
  void initState() {
    super.initState();
    _startDateTime = DateTime.now();
    _scrollController = AnimatedScrollController(animationFactory: const ChromiumEaseInOut());
  }

  void _receivedPointerSignal(PointerSignalEvent event) {
    if (!kDebugMode) return;

    if (event is PointerScrollEvent) {
      debugPrint('PointerScrollEvent(dx: ${event.scrollDelta.dx}, dy: ${event.scrollDelta.dy})');
    } else if (event is PointerScrollInertiaCancelEvent) {
      debugPrint('PointerScrollInertiaCancelEvent()');
    }
  }

  bool _receivedScrollNotification(ScrollNotification notification) {
    if (!kDebugMode) return false;

    if (notification is ScrollStartNotification) {
      debugPrint('ScrollStartNotification()');
    } else if (notification is ScrollEndNotification) {
      debugPrint('ScrollEndNotification()');
    } else if (notification is ScrollUpdateNotification) {
      debugPrint('ScrollUpdateNotification(delta: ${notification.scrollDelta})');
    } else if (notification is UserScrollNotification) {
      debugPrint('UserScrollNotification(direction: ${notification.direction})');
    } else {
      debugPrint(notification.toString());
    }

    return false;
  }

  [@override](/user/override)
  void dispose() {
    _scrollController.dispose();
    super.dispose();
  }

  [@override](/user/override)
  Widget build(BuildContext context) => Listener(
    onPointerSignal: _receivedPointerSignal,
    child: NotificationListener<ScrollNotification>(
      onNotification: _receivedScrollNotification,
      child: ListView.builder(
        controller: _scrollController,
        itemCount: 100,
        itemBuilder: (context, index) => ListTile(
          title: Text('Item $index'),
        ),
      ),
    ),
  );
}

更多关于Flutter滚动动画插件scroll_animator的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter滚动动画插件scroll_animator的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,关于Flutter中的scroll_animator插件的使用,下面是一个具体的代码案例,展示了如何实现滚动动画效果。scroll_animator插件允许你在Flutter应用中轻松地为滚动视图添加动画效果。

首先,确保你已经在pubspec.yaml文件中添加了scroll_animator依赖:

dependencies:
  flutter:
    sdk: flutter
  scroll_animator: ^x.y.z  # 替换为最新版本号

然后,运行flutter pub get来安装依赖。

接下来是一个完整的示例代码,展示如何使用scroll_animator来实现滚动动画:

import 'package:flutter/material.dart';
import 'package:scroll_animator/scroll_animator.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Scroll Animator Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
  late ScrollController _scrollController;
  late AnimationController _animationController;

  @override
  void initState() {
    super.initState();
    _scrollController = ScrollController();
    _animationController = AnimationController(
      duration: const Duration(seconds: 2),
      vsync: this,
    )..repeat(reverse: true);
  }

  @override
  void dispose() {
    _scrollController.dispose();
    _animationController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Scroll Animator Demo'),
      ),
      body: ScrollAnimator(
        scrollController: _scrollController,
        animationController: _animationController,
        animationBuilder: (context, scrollPosition, animation) {
          return AnimatedBuilder(
            animation: animation,
            child: Container(
              height: 200,
              color: Colors.amber,
              child: Center(child: Text('Animated Content')),
            ),
            builder: (context, child) {
              return Transform.translate(
                offset: Offset(0, animation.value * 50), // 调整动画效果
                child: child,
              );
            },
          );
        },
        child: ListView.builder(
          controller: _scrollController,
          itemCount: 20,
          itemBuilder: (context, index) {
            return ListTile(
              title: Text('Item $index'),
            );
          },
        ),
      ),
    );
  }
}

代码解释

  1. 依赖导入: 确保在pubspec.yaml中添加了scroll_animator依赖,并运行flutter pub get

  2. 初始化: 在_MyHomePageState中,我们初始化了ScrollControllerAnimationControllerAnimationController用于控制动画的时长和循环。

  3. ScrollAnimator的使用

    • scrollController:绑定到ListView的滚动控制器。
    • animationController:绑定到动画控制器。
    • animationBuilder:一个函数,用于构建动画效果。在这个例子中,我们使用AnimatedBuilderTransform.translate来创建一个简单的垂直平移动画。
  4. ListView: 使用ListView.builder来生成一个包含多个ListTile的列表。

当你滚动列表时,绑定的动画将会根据滚动位置触发,从而在指定的内容上应用动画效果。

请注意,scroll_animator插件的具体API和使用方式可能会随着版本更新而变化,因此建议查阅最新的官方文档以获取最准确的信息。

回到顶部