Flutter实战一Flutter聊天应用(三)

119 篇文章 9 订阅
82 篇文章 1416 订阅

我们可以向控件添加动画效果,使应用程序的用户体验更加流畅和直观。在这篇文章中,我们将在聊天消息列表中添加基本动画效果。当用户发送新消息时,我们不要将其简单地显示在消息列表中,我们将从列表底部垂直放置消息。

Flutter中的动画被封装为包含类型值和状态(如前进、后退、完成和关闭)的Animation对象,我们可以将动画对象附加到控件或监听动画对象的更改。基于对动画对象属性的更改,框架可以修改窗口控件的显示方式并重新构建窗口控件。

使用AnimationController类来指定动画应该如何运行,AnimationController类可以让我们定义动画的重要特征,例如其持续时间和播放方向(正向或反向)。当创建AnimationController对象时,我们需要传递一个vsync参数。此选项将当前窗口控件树保留在显示内存中,直到Flutter的渲染引擎完成刷新周期。想要将我们的ChatScreenState作为vsync,需要在ChatScreenState类定义中包含一个TickerProviderStateMixin

class ChatScreenState extends State<ChatScreen> with TickerProviderStateMixin {
  final List<ChatMessage> _messages = <ChatMessage>[];
  final TextEditingController _textController = new TextEditingController();
  //...

ChatScreenState类中修改_handleSubmitted()方法,在此方法中,实例化一个AnimationController对象并将动画的运行时间指定为700毫秒。在这里我们选择了较长的持续时间来减慢动画效果,以便我们可以逐渐看到转换。实际上,我们在后面会设置较短的持续时间,并在运行应用程序时禁用慢速模式。

ChatMessage类定义中,添加一个成员变量来存储动画控制器。

class ChatMessage extends StatelessWidget {
  ChatMessage({this.text, this.animationController});
  final String text;
  final AnimationController animationController;
  //...

将动画控制器附加到新的ChatMessage实例,并指定每当将新消息添加到聊天列表中时动画应播放。

class ChatScreenState extends State<ChatScreen> with TickerProviderStateMixin {
  //...
  void _handleSubmitted(String text) {
    _textController.clear();
    ChatMessage message = new ChatMessage(
      text: text,
      animationController: new AnimationController(
        duration: new Duration(milliseconds: 700),
        vsync: this
      )
    );
    setState((){
      _messages.insert(0, message);
    });
    message.animationController.forward();
  }
  //...
}

修改ChatMessageListItem对象的build()方法以返回一个SizeTransition控件,该控件包装我们之前定义的Container控件。SizeTransition类提供了一个动画效果,其子控件的宽度或高度乘以给定的大小因子值。

CurvedAnimation对象与SizeTransition类结合使用可以产生一个简单的动画效果。缓解效果会使消息在动画开始时快速滑动,并减慢速度直到停止。

class ChatMessage extends StatelessWidget {
  //...
  Widget build(BuildContext context) {
    return new SizeTransition(
      sizeFactor: new CurvedAnimation(
        parent: animationController,
        curve: Curves.easeOut
      ),
      axisAlignment: 0.0,
      child: new Container(
        margin: const EdgeInsets.symmetric(vertical: 10.0),
        child: new Row(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            new Container(
              margin: const EdgeInsets.only(right: 16.0),
              child: new CircleAvatar(child: new Text(_name[0])),
            ),
            new Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                new Text(_name, style: Theme.of(context).textTheme.subhead),
                new Container(
                  margin: const EdgeInsets.only(top: 5.0),
                  child: new Text(text),
                )
              ]
            )
          ]
        )
      )
    );
  }
  //...
}

处理动画控制器以在我们不再需要资源时释放资源是个好习惯,下面的代码片段显示了如何通过在ChatScreenState中覆盖dispose()方法来实现此操作。在当前的应用程序中,该框架不会调用dispose()方法,因为该应用程序只有一个屏幕。在具有多个屏幕的更复杂的应用程序中,当ChatScreenState对象不再使用时,框架将调用该方法。

class ChatScreenState extends State<ChatScreen> with TickerProviderStateMixin {
  //...
  @override
  void dispose() {
    for(ChatMessage message in _messages)
      message.animationController.dispose();
    super.dispose();
  }
  //...
}

这里写图片描述

这里有一个小细节,我们的应用程序在右上角有一个“SLOW MODE”横幅。因为在默认情况下,flutter run命令使用调试构建配置。调试配置在Dart虚拟机(Dart Virtual Machine)中运行Dart代码,从而实现快速重新加载的开发周期。发布版本则是使用标准的Android和iOS工具链进行编译。

调试配置还会检查所有的断言,这有利于我们在开发过程中尽早捕获错误,但是这也会增加运行时的成本。“SLOW MODE”横幅表示启用这些检查。我们可以通过使用--profile--release标志到flutter run来运行应用程序,而不进行这些检查。这就是我在上面提到的禁用慢速模式。

在上面代码中,我们将动画的运行时间指定为700毫秒,是为了可以看到动画的转换过程, 实际上我们可以把这个时间设置成300毫秒,或者其他更合适的时间。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

何小有

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值