Flutter动画值管理插件animated_value的使用

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

Flutter 动画值管理插件 animated_value 的使用

animated_value 插件为 Flutter 提供了一种简单且灵活的方式来动画化值。它使用自定义的 lerp(线性插值)函数或自定义构建器函数来创建平滑的动画效果。所有的动画都是隐式的,就像在 AnimatedContainer 中更改值一样简单。

使用示例

下面是一个基本的例子,展示了如何使用 AnimatedValue 小部件来动画化 ButtonStyle

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

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

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Animated Value Example')),
        body: Center(child: AnimatedButtonExample()),
      ),
    );
  }
}

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

class _AnimatedButtonExampleState extends State<AnimatedButtonExample> {
  bool _isPressed = false;

  final ButtonStyle buttonStyle1 = ElevatedButton.styleFrom(
    primary: Colors.blue,
    onPrimary: Colors.white,
    padding: EdgeInsets.symmetric(horizontal: 20, vertical: 15),
    textStyle: TextStyle(fontSize: 16),
  );

  final ButtonStyle buttonStyle2 = ElevatedButton.styleFrom(
    primary: Colors.red,
    onPrimary: Colors.black,
    padding: EdgeInsets.symmetric(horizontal: 30, vertical: 20),
    textStyle: TextStyle(fontSize: 20),
  );

  void _toggleButtonStyle() {
    setState(() {
      _isPressed = !_isPressed;
    });
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        AnimatedValue<ButtonStyle?>(
          // 要动画化的值
          value: _isPressed ? buttonStyle2 : buttonStyle1,

          // 可选的 `lerp()` 函数用于复杂对象
          lerp: ButtonStyle.lerp,

          // 在动画过程中重建小部件
          builder: (context, value, _) {
            return ElevatedButton(
              style: value,
              onPressed: _toggleButtonStyle,
              child: Text('点击我'),
            );
          },
        ),
      ],
    );
  }
}

自定义插值

animated_value 插件提供了 LerpTween 类和 LerpCallback 类型,用于在两个值之间进行自定义插值。以下是一个简要的解释和使用示例:

final tween = LerpTween(
  begin: ...,
  end: ...,
  lerp: AppBarTheme.lerp,
);

扩展方法

animated_value 插件还为 LerpCallback 类提供了扩展方法,使得创建 LerpTween 对象更加容易。以下是一个使用这些扩展方法的示例:

final tween = AppBarTheme.lerp.tween(begin: ..., end: ...);

完整示例 Demo

为了更好地理解 animated_value 插件的使用,以下是一个完整的示例应用,展示了如何使用 AnimatedValue 来动画化按钮样式和 AppBarTheme

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

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

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Animated Value Example'),
        ),
        body: Center(child: AnimatedButtonAndAppBarExample()),
      ),
    );
  }
}

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

class _AnimatedButtonAndAppBarExampleState extends State<AnimatedButtonAndAppBarExample> {
  bool _isPressed = false;

  final ButtonStyle buttonStyle1 = ElevatedButton.styleFrom(
    primary: Colors.blue,
    onPrimary: Colors.white,
    padding: EdgeInsets.symmetric(horizontal: 20, vertical: 15),
    textStyle: TextStyle(fontSize: 16),
  );

  final ButtonStyle buttonStyle2 = ElevatedButton.styleFrom(
    primary: Colors.red,
    onPrimary: Colors.black,
    padding: EdgeInsets.symmetric(horizontal: 30, vertical: 20),
    textStyle: TextStyle(fontSize: 20),
  );

  final AppBarTheme appBarTheme1 = AppBarTheme(
    color: Colors.blue,
    elevation: 4,
  );

  final AppBarTheme appBarTheme2 = AppBarTheme(
    color: Colors.red,
    elevation: 8,
  );

  void _toggleStyles() {
    setState(() {
      _isPressed = !_isPressed;
    });
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        // 动画化按钮样式
        AnimatedValue<ButtonStyle?>(
          value: _isPressed ? buttonStyle2 : buttonStyle1,
          lerp: ButtonStyle.lerp,
          builder: (context, value, _) {
            return ElevatedButton(
              style: value,
              onPressed: _toggleStyles,
              child: Text('点击我'),
            );
          },
        ),
        SizedBox(height: 20),
        // 动画化 AppBarTheme
        AnimatedValue<AppBarTheme>(
          value: _isPressed ? appBarTheme2 : appBarTheme1,
          lerp: AppBarTheme.lerp,
          builder: (context, value, _) {
            return AppBar(
              backgroundColor: value.color,
              elevation: value.elevation,
              title: Text('动态 AppBar'),
            );
          },
        ),
      ],
    );
  }
}

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

1 回复

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


当然,animated_value 是一个在 Flutter 中用于管理动画值的插件。它允许你创建和管理动画值,并能够在动画运行时实时更新这些值。以下是一个简单的代码示例,展示了如何使用 animated_value 插件来创建一个基本的动画。

首先,你需要在你的 pubspec.yaml 文件中添加 animated_value 依赖:

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

然后运行 flutter pub get 来获取依赖。

接下来是一个完整的 Flutter 应用示例,展示如何使用 animated_value 来创建一个简单的动画:

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

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

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

class AnimatedValueDemo extends StatefulWidget {
  @override
  _AnimatedValueDemoState createState() => _AnimatedValueDemoState();
}

class _AnimatedValueDemoState extends State<AnimatedValueDemo> with SingleTickerProviderStateMixin {
  late AnimatedValueController<double> _controller;

  @override
  void initState() {
    super.initState();
    // 初始化 AnimatedValueController,设置初始值、最小值和最大值
    _controller = AnimatedValueController(
      value: 0.0,
      lowerBound: 0.0,
      upperBound: 1.0,
      duration: Duration(seconds: 2),
      vsync: this,
    )..addListener(() {
        // 监听动画值的变化,并在UI中更新
        setState(() {});
      });

    // 开始动画,从0到1
    _controller.animateTo(1.0);
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Animated Value Demo'),
      ),
      body: Center(
        child: AnimatedBuilder<double>(
          animation: _controller,
          builder: (context, child, value) {
            // 使用动画值来改变UI,例如改变一个容器的高度
            return Container(
              height: value * 200,
              width: 200,
              color: Colors.blue,
              child: Center(
                child: Text(
                  'Value: ${value.toStringAsFixed(2)}',
                  style: TextStyle(color: Colors.white),
                ),
              ),
            );
          },
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          // 点击按钮时,重新开始动画
          _controller.reset();
          _controller.animateTo(1.0);
        },
        tooltip: 'Restart Animation',
        child: Icon(Icons.replay),
      ),
    );
  }
}

在这个示例中,我们创建了一个 AnimatedValueController 来管理动画值。AnimatedValueControllervalue 属性表示当前的动画值,lowerBoundupperBound 属性定义了动画值的最小值和最大值,duration 属性定义了动画的持续时间。

initState 方法中,我们初始化 AnimatedValueController 并开始动画,从0到1。我们添加了一个监听器来在动画值变化时调用 setState 方法,从而更新UI。

build 方法中,我们使用 AnimatedBuilder 来监听动画值的变化,并根据动画值动态更新UI。这里,我们根据动画值改变了一个容器的高度,并在容器内显示当前的动画值。

浮动操作按钮(FAB)用于重新开始动画。当点击按钮时,我们调用 _controller.reset() 方法重置动画,然后再次调用 _controller.animateTo(1.0) 开始动画。

这样,你就可以使用 animated_value 插件来创建和管理动画值了。希望这个示例对你有所帮助!

回到顶部