Flutter实现动画卡片式Tab导航

前言

本人接触Flutter不到一个月,深深感受到了这个平台的威力,于是不断学习,Flutter官方Example中的flutter_gallery有一个非常好看的动画卡片式的Tab导航,很好的展示了Flutter各个widget的功能

其中的animation内容,展示的是一个带有动画和拖拽功能的 可展开的卡片式Tab导航,非常漂亮,但是其实现没有抽象出一个可供第三方使用的Widget出来,而且其页面内容的定制性不够友好,滑动的时候也有bug,我在他的基础上进行了优化

官方展示了一个非常好的开源示例,我改造了一下,也不敢独自享用,现在分享给大家,欢迎大家多多交流

外观

实现

这里是我的代码: GitHub/Realank

想使用这个控件非常简单,首先定义页面数据:

const Color _mariner = const Color(0xFF3B5F8F);
const Color _mediumPurple = const Color(0xFF8266D4);
const Color _tomato = const Color(0xFFF95B57);
const Color _mySin = const Color(0xFFF3A646);

List<CardSection> allSections = <CardSection>[
  new CardSection(
      title: 'First Page',
      leftColor: _mediumPurple,
      rightColor: _mariner,
      contentWidget: Center(child: new Text('第一页'))),
  new CardSection(
      title: 'Second Page',
      leftColor: _mariner,
      rightColor: _mySin,
      contentWidget: Center(child: new Text('第二页'))),
  new CardSection(
      title: 'Third Page',
      leftColor: _mySin,
      rightColor: _tomato,
      contentWidget: Center(child: new Text('第三页'))),
  new CardSection(
      title: 'Forth Page',
      leftColor: _tomato,
      rightColor: Colors.blue,
      contentWidget: Center(child: new Text('第四页'))),
  new CardSection(
      title: 'Fifth Page',
      leftColor: Colors.blue,
      rightColor: _mediumPurple,
      contentWidget: Center(child: new Text('第五页'))),
];

然后创建这个控件:

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      home: new Scaffold(
        body: Center(
          child: new AnimateTabNavigation(
            sectionList: allSections,
          ),
        ),
      ),
    );
  }
}

大功告成

原理

知其然还要知其所以然,下面来说说这个控件的实现原理

首先,在sections.dart里定义了数据结构:


class CardSection {
  CardSection({this.title, this.leftColor, this.rightColor, this.contentWidget});

  final String title;
  final Color leftColor;
  final Color rightColor;
  final Widget contentWidget;

  @override
  bool operator ==(Object other) {
    if (other is! CardSection) return false;
    final CardSection otherSection = other;
    return title == otherSection.title;
  }

  @override
  int get hashCode => title.hashCode;
}

它定义了其中一个卡片的标题,左边颜色和右边颜色(为了显示过渡颜色效果),以及子控件(这个是我改进的,这样可以别人使用的时候随意添加控件)

然后在widgets.dart中定义了几个widget:

  • SectionCard : 标题卡片
  • SectionTitle : 标题
  • SectionIndicator : 标题下的装饰线

最后在cardNavigation.dart中就是布局这些内容啦,这里面代码很复杂,其思路倒是不难:

  1. 定义全屏展示tab的高度maxHeight,以及打开tab后,tab显示在顶部的高度minHeight
  2. 在用户拖动tab卡片的时候,根据卡片的位置于minHeight和maxHeight的比例,计算出动画进度(0.0-1.0)
  3. 在_AllSectionsLayout中,定义了全屏显示tab时,卡片的columnCardRect,以及打开tab后,tab显示在顶部时候的rowCardRectt
  4. 计算出这两个rect在动画进度0-1过程中的中间态的rect尺寸,赋值给每一个卡片,这样卡片就有中间状态的外观了。
  5. 当用户点击了tab区域,就会触发_maybeScroll方法,这个方法判断当前的tab是全屏的还是打开后的
  6. 当tab是全屏的,就展开对应的tab页
  7. 当tab已经是打开的,就判断点击的位置,在tab栏的左侧,就往左翻页,反之亦然。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,525评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,203评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,862评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,728评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,743评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,590评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,330评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,244评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,693评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,885评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,001评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,723评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,343评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,919评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,042评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,191评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,955评论 2 355

推荐阅读更多精彩内容

  • 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SD...
    阳明先生_X自主阅读 15,981评论 3 119
  • 别自作多情了 尽管你专程而来 那么深情干嘛 我敞开的门 只为天空 费尽心思杜撰着 我的寂寞 其实我 习惯了孤独 你...
    一杯老酒阅读 1,253评论 29 17
  • 满地的落叶见证了秋的结束。 他和她来到这里。 相恋三年,彼此深深地刻在对方骨子里。他是刑警,要去执行任务,在这片树...
    我爱健康阅读 212评论 2 2
  • 七夕至,鹊桥边,来相会,人未至,心已醉。 月亮船,花海边,一玫瑰,望秋水,相思泪。 银河岸,各一边,繁星点,借明月...
    快乐的Alina阅读 470评论 21 23
  • 看到这个题目,以你一定得奇怪,世上哪有这种糖。我怎么没见过,看来不动脑筋是不行的我不发,直接告诉你吧。 那天晚饭后...
    小美su阅读 549评论 0 0