美文网首页
Flutter实现动画卡片式Tab导航

Flutter实现动画卡片式Tab导航

作者: Realank | 来源:发表于2018-08-03 15:50 被阅读1029次

    前言

    本人接触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栏的左侧,就往左翻页,反之亦然。

    相关文章

      网友评论

          本文标题:Flutter实现动画卡片式Tab导航

          本文链接:https://www.haomeiwen.com/subject/gotuvftx.html