Flutter实现抽屉动画效果菜鸟教程网_动画小白知识

这篇会深化View拖拽实例,利用Flutter Animation、插值器以及AnimatedBuilder教大家实现带动画的抽屉效果。通过构思,我们可以设想到实现抽屉的方式就是用Stack控件将两个Widget叠加显示,用GestureDetector监听手势滑动,动态移动顶层的Widget,当监听到手势结束的时候根据手势滑动的距离动态将顶部Widget利

Flutter实现抽屉动画效果菜鸟教程网

这篇会深化View拖拽实例,利用Flutter Animation、插值器以及AnimatedBuilder教大家实现带动画的抽屉效果。

Flutter实现抽屉动画效果菜鸟教程网_动画小白知识

通过构思,我们可以设想到实现抽屉的方式就是用Stack控件将两个Widget叠加显示,用GestureDetector监听手势滑动,动态移动顶层的Widget,当监听到手势结束的时候根据手势滑动的距离动态将顶部Widget利用动画效果滑动到结束位置即可。

实现底部Widget

class DownDrawerWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(child: Center(child: Text("底部Widget",),),);
  }
}

这个Widget太简单了,就不细说了。

实现顶部Widget

class UpDrawerWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(child: Center(child: Text("顶部Widget",),),);
  }
}

实现方式和底部是一样的。

实现可以移动的容器

上面两个Widget都是单纯用来显示的Widget,因此继承了StatelessWidget。接下来我们需要根据手势动态移动顶部的Widget,因此需要继承StatefulWidget。

// 顶部Widget
class HomePageWidget extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => HomePageState();
}

class HomePageState extends State<HomePageWidget>
    with SingleTickerProviderStateMixin {

  @override
  void initState() {...}

  @override
  void dispose() {...}

  @override
  Widget build(BuildContext context) {...}

  void _onViewDragDown(DragDownDetails callback) {...}

  void _onViewDrag(DragUpdateDetails callback) {...}

  void _onViewDragUp(DragEndDetails callback) {...}
}

初始化状态initState()

这个方法是在Widget初始化的时候系统的回调函数,我们需要在该函数中初始化动画

AnimationController controller;
@override
void initState() {
    // 初始化动画控制器,这里限定动画时常为200毫秒
    controller = new AnimationController(vsync: this, duration: const Duration(milliseconds: 200));
    // vsync对象会绑定动画的定时器到一个可视的widget,所以当widget不显示时,动画定时器将会暂停,当widget再次显示时,动画定时器重新恢复执行,这样就可以避免动画相关UI不在当前屏幕时消耗资源。
    // 当使用vsync: this的时候,State对象必须with SingleTickerProviderStateMixin或TickerProviderStateMixin;TickerProviderStateMixin适用于多AnimationController的情况。

    // 设置动画曲线,就是动画插值器
    // 通过这个链接可以了解更多差值器,https://docs.flutter.io/flutter/animation/Curves-class.html,我们这里使用带回弹效果的bounceOut。
    CurvedAnimation curve =
        new CurvedAnimation(parent: controller, curve: Curves.bounceOut);

    // 增加动画监听,当手势结束的时候通过动态计算到达目标位置的距离实现动画效果。curve.value为当前动画的值,取值范围0~1。
    curve.addListener(() {
      double animValue = curve.value;
      double offset = dragUpDownX - dragDownX;
      double toPosition;

      // 右滑
      if (offset > 0) {
        if (offset > maxDragX / 5) {
          // 打开
          toPosition = maxDragX;
          isOpenState = true;
        } else {
          if (isOpenState) {
            toPosition = maxDragX;
            isOpenState = true;
          } else {
            toPosition = 0.0;
            isOpenState = false;
          }
        }
      } else {
        if (offset < (-maxDragX / 2.0)) {
          // 关
          toPosition = 0.0;
          isOpenState = false;
        } else {
          if (isOpenState) {
            toPosition = maxDragX;
            isOpenState = true;
          } else {
            toPosition = 0.0;
            isOpenState = false;
          }
        }
      }

      dragOffset = (toPosition - dragUpDownX) * animValue + dragUpDownX;
      // 刷新位置
      setState(() {});
    });
  }

结束Widget dispose()

当Widget不可用将被回收的时候,系统会回调dispose()方法,我们在这里回收动画。

@override
void dispose() {
    controller.dispose();
}

记录按下的位置

    double dragDownX = 0.0;
  void _onViewDragDown(DragDownDetails callback) {
    dragDownX = callback.globalPosition.dx;
  }

拖动的时候刷新View的位置

/**
   * 最大可拖动位置
   */
  final double maxDragX = 230.0;
  double dragOffset = 0.0;
  void _onViewDrag(DragUpdateDetails callback) {
    double tmpOffset = callback.globalPosition.dx - dragDownX;

    if (tmpOffset < 0) {
      tmpOffset += maxDragX;
    }

    // 边缘检测
    if (tmpOffset < 0) {
      tmpOffset = 0.0;
    } else if (tmpOffset >= maxDragX) {
      tmpOffset = maxDragX;
    }

    // 刷新
    if (dragOffset != tmpOffset) {
      dragOffset = tmpOffset;
      setState(() {});
    }
  }

离手的时候记录位置并执行动画

  /**
   * 脱手时候的位置
   */
  double dragUpDownX = 0.0;
  void _onViewDragUp(DragEndDetails callback) {
    dragUpDownX = dragOffset;
    // 执行动画,每次都从第0帧开始执行
    controller.forward(from: 0.0);
  }

支持移动的Widget

@override
  Widget build(BuildContext context) {
    return Transform.translate(
      offset: Offset(dragOffset, 0.0),
      child: Container(
        child: GestureDetector(
              onHorizontalDragDown: _onViewDragDown,
              onVerticalDragDown: _onViewDragDown,
              onHorizontalDragUpdate: _onViewDrag,
              onVerticalDragUpdate: _onViewDrag,
              onHorizontalDragEnd: _onViewDragUp,
              onVerticalDragEnd: _onViewDragUp,
              child: Container(
                child: new UpDrawerWidget(),
          ),),),);}

Flutter动画

总结一下,想在Flutter中实现动画,需要先创建一个AnimationController控制器;如果有特殊的插值要求,再创建一个插值器,调用controller.forward()方法执行动画,通过addListener()的回调改变对应数值之后调用setState(() {})方法刷新位置即可。
Flutter API还提供AnimatedBuilder用来简化实现动画的复杂性,让我们不用手动调用addListener()方法。

海计划公众号
(0)
上一篇 2020/03/29 01:42
下一篇 2020/03/29 01:42

您可能感兴趣的内容

  • 如何使用Vue.js 开发以太坊DApp入门教程_区块链新手入门

    Vue 是一套在前端开发中广泛采用的用于构建用户界面的渐进式JavaScript框架。Vue 通过响应的数据绑定和组合的视图组件让界面开发变得非常的简单。这边文章来看看如何使用Vue开发以太坊DApp。Vue 简介Vue 除了是JavaScript框架,还提供了一个配套的命令行工具 Vue CLI,通常称之为脚手架工具,用来进行项目管理,比如快速开始零配置原

    2020/03/20
  • WebODM使用教程_从无人机图像生成地图,点云,纹理三维模型

    WebODM使用教程 官方网址:https://www.opendronemap.org/webodm/ GitHub:https://github.com/OpenDroneMa…

    2020/03/10
  • CSS float相关介绍入门基础知识_float指南教程

    一、float介绍float元素也称为浮动元素,设置了float属性的元素会根据属性值向左或向右浮动。浮动元素会从普通文档流中脱离,但浮动元素影响的不仅是自己,它会影响周围的元素对齐进行环绕。简单来说,就是让block元素无视float元素,让inline元素让流水一样围绕着float元素来实现浮动布局。 文字环绕图片是float典型的应用场景,如下所示:h

    2020/03/23
  • canvas生成带二维码的海报踩坑使用攻略_二维码小白常识

    canvas海报内容有背景图,圆形头像,用户昵称,链接的二维码图片。问题如下图片不显示绘制渲染的时候图像不显示:是因为图片异步加载,所以canvas的操作需要放在onload事件中,否则图片会不显示,因为图片不止一张,建议放在promise中,用async,await调用canvas最终生成图片分享出去,生成的图片不显示:是因为图像跨域问题,设置img的at

    2020/03/26
  • 常用正则表达式基础知识_正则使用帮助

    表达式全集字符描述\将下一个字符标记为一个特殊字符、或一个原义字符、或一个向后引用、或一个八进制转义符。例如,“n”匹配字符“n”。“\n”匹配一个换行符。串行“\\”匹配“\”而“\(”则匹配“(”。^匹配输入字符串的开始位置。如果设置了RegExp对象的Multiline属性,^也匹配“\n”或“\r”之后的位置。$匹配输入字符串的结束位置。如果设置了R

    2020/03/24
  • HTML5全局属性汇总小白教程_html5小白攻略

    局部属性和全局属性 局部属性:有些元素能规定自己的属性,这种属性称为局部属性。比如link元素,它具有的局部属性有href、 rel、 hreflang、 media、 type、 sizes这六个。全局属性:可以用来配置所有元素共有的行为,这种属性称为全局属性,可以用在任何一个元素身上。1、accesskey属性使用accesskey属性可以设定一个或几

    2020/04/06
  • angular有必要学吗?基础知识入门_angular入门基础

    对于前端开发人员来说,angular是非常有必要学习的,它可以使Web应用开发比以往更简单、更快捷;同时也降低了构建复杂应用的难度。更何况很多后端职位都要求掌握angular了。Angular是一个使用 HTML 和 JavaScript 编写的 Web 前端框架,可用于编写一个页面的 JavaScript 应用,这些应用可以多次使用或稍作调整以供将来使用。

    2020/03/22
  • grumble.js小白攻略一款可360度旋转的气泡样式jQuery提示框插件

    grumble.js基础入门 官方网址:http://jamescryer.github.com/grumble.js/ GitHub:https://github.com/jam…

    2020/03/05
  • 低效率开发人员的4种坏习惯基础入门_效率小白指南

    我们都有不好的习惯,地球上没有一个人是完美的。作为开发人员,不良习惯会严重影响您的效率,也会影响您周围的人。Jack Canfield说:“习惯将决定您的未来”。想要成长为一名开发人员,就必须改掉不良习惯。如果您可以做到,效率将大大提高。让我们看看您应该尽快改掉的坏习惯。永远说“是”首先声明一点,对所有事情都说 是 谦虚且无私的,这意味着您愿意(可能需要付出

    2020/03/23
  • 前端工程师遇到bug时的5个搞笑反应菜鸟指南_bug入门基础教程

    Bug是程序员常常碰见的,有人会生气,有人会沮丧,有人会心烦意乱,当然啦,也有人会依然保持冷静沉着。那么小编带大家来看看html5前端工程师遇到bug时的10个反应,有些搞笑哦~ 1.“我不知道是要删除还是要重写它”回顾从前老的源代码,会有一种想要返工写成较大块集群的冲动和诱惑。丑陋的逻辑语句,还有冗长的语法,导致代码非常难以阅读!但话又说回来,如果代码没

    2020/03/31
  • elasticode小白攻略_优秀APP交互动效收集

    elasticode小白攻略 官方网址:http://www.elasticode.com/ 简介描述:优秀APP交互动效收集 Elasticode堪称H5交互动效收录库。各类供你…

    2020/03/10
  • javascript的基本特点有哪些?小白帮助_特点使用指南

    JavaScript(通常缩写为JS)是一种高级的、解释型的编程语言;它是一门基于原型、函数先行的语言,是一门多范式的语言,它支持面向对象编程,命令式编程,以及函数式编程。javascript的基本特点1、javascript是一种解释性执行的脚本语言同其他脚本语言一样,JavaScript也是一种解释性语言,其提供了一个非常方便的开发过程。JavaScri

    2020/03/20
  • 腾讯云活动、优惠券小白入门_云服务器,云数据库,CDN,域名注册等多种云计算服务

    腾讯云活动、优惠券小白入门 简介描述:云服务器,云数据库,CDN,域名注册等多种云计算服务 腾讯云于2013年09 月面向全社会开放、云安全上线,为全球客户提供领先的云计算、大数据…

    2020/03/11
  • vim-web:像 IDE 一样的 Vim,安装配置自己的 Vim攻略教程_IDE小白指南

    在 vim-web v2 版本插件配置太多,新版本 v3 只配置少量的插件,是一个简单的版本。安装最新版本的Vim 8.1+ 使用下面命令安装 vim 版本并更新:brew install macvim # 安装 macvim
    brew install macvim –override-system-vim将插件以及配置下载到 ~/.vim/ 目录中,这个

    2020/03/29
  • 程序员生存宝典,平时需要注意的一些“潜规则”零基础入门_程序员使用教程

    1.对普通的中高级管理岗,也始终坚持从内部提拔。至少我眼力所及,在公司服务的10年时间里,还没见过一个空降的中级管理岗。2.做技术 的,可以转管理,可以转架构,也可以转教学。但是反过来却不成立,尤其是在一日千里的IT行业,脱离技术,最多只用3年,技术基本也就“废”了。3.世上所有的事情都是有两面性的,也大概是公平的,你得到一些,也必然会失去一些。4.主动高效

    2020/03/23
  • css修改浏览器默认滚动条样式入门攻略_滚动使用说明

    写过挺多项目都需要改变滚动条的默认样式 并不想单独下载和引入插件 因此纯css修改默认滚动条的样式 这次算统一整理下方法,直接上代码。&::-webkit-scrollbar {// 滚动条的背景width: 16px;background: #191a37;height: 14px;
    }&::-webkit-scrollbar-track,
    &::-web

    2020/03/26