Flutter 126: 图解自定义两侧对齐 ACETabBar 标签导航栏

简介: 0 基础学习 Flutter,第一百二十六步:简单定义一个可设置左右两侧对齐方式及两侧固定位 Icon 的 ACETabBar 导航栏!

    小菜在实践学习过程中,需要把 TabBar 标签栏默认居左,而 TabBar 默认是居中状态;小菜借此机会学习一下 TabBar 源码,稍微调整一下对齐方式;

ACETabBar

ACETabBarAlignType 对齐方式

    小菜添加了一个 alignType 用于设置 ACETabBar 对齐方式;同时设置 isScrollable = true;当 isScrollable = false 时与 TabBar 默认占满屏幕均分效果一致;

enum ACETabBarAlignType { left, center, right }

源码分析

    小菜分析 TabBar 源码,在 _TabBarStateTabBar 绘制过程中,多个子 Tab 通过 SingleChildScrollView 存放,最简单的方式,在 SingleChildScrollView 外添加可以设置对齐方式的 Container 即可;

if (widget.isScrollable) {
  _scrollController ??= _TabBarScrollController(this);
  tabBar = Container(
      alignment: _alignType(widget.alignType ?? ACETabBarAlignType.center),
      child: _scrollView(tabBar));
}

_alignType(alignType) {
  Alignment _type;
  switch (alignType) {
    case ACETabBarAlignType.left:
      _type = Alignment.centerLeft;
      break;
    case ACETabBarAlignType.center:
      _type = Alignment.center;
      break;
    case ACETabBarAlignType.right:
      _type = Alignment.centerRight;
      break;
  }
  return _type;
}

_scrollView(tabBar) {
  return SingleChildScrollView(
      dragStartBehavior: widget.dragStartBehavior,
      scrollDirection: Axis.horizontal,
      controller: _scrollController,
      physics: widget.physics,
      child: tabBar);
}

案例尝试

    小菜尝试了在 isScrollable 是否可滑动两种状态下,ACETabBar 的对齐方式;

_tabBar01() => ACETabBar(
    isScrollable: true, 
    controller: _tabController, tabs: <Widget>[
      Tab(text: '今日', icon: Icon(Icons.account_circle)),
      Tab(text: '今日爆款土货生鲜'),
      Tab(text: '分类')
    ]);
    
_tabBar02() => ACETabBar(
    isScrollable: true,
    alignType: ACETabBarAlignType.left,
    controller: _tabController,
    tabs: <Widget>[
      Tab(text: '今日爆款'),
      Tab(text: '今日爆款土货生鲜'),
      Tab(text: '分类')
    ]);

_tabBar03() => ACETabBar(
    isScrollable: true,
    alignType: ACETabBarAlignType.right,
    controller: _tabController,
    tabs: <Widget>[
      Tab(text: '今日爆款'),
      Tab(text: '今日爆款土货生鲜'),
      Tab(text: '分类')
    ]);
    
_tabBar04() => ACETabBar(
    isScrollable: false,
    alignType: ACETabBarAlignType.right,
    controller: _tabController,
    tabs: <Widget>[
      Tab(text: '今日爆款'),
      Tab(text: '今日爆款土货生鲜'),
      Tab(text: '分类')
    ]);

startIcon & endIcon 固定位图标

    类似很多新闻类或商城类 app,在 TabBar 所在的左右两侧通常会有固定的图标或文字等小 Widget;而小菜也在设置完对齐方式后增加了 startIcon & endIcon 两个图标位;

源码分析

    小菜在设置对齐方式的时了解到 _TabBarState 用于绘制展示是否可滑动的 TabBar,小菜增加两个 startIcon & endIcon 两个属性,在最终 return tabBar 时进行判断是否展示添加到导航栏中;而是否添加点击事件可以通过添加 Widget 时进行处理;

Widget tabBar = CustomPaint(
    painter: _indicatorPainter,
    child: _TabStyle(
        animation: kAlwaysDismissedAnimation,
        selected: false,
        labelColor: widget.labelColor,
        unselectedLabelColor: widget.unselectedLabelColor,
        labelStyle: widget.labelStyle,
        unselectedLabelStyle: widget.unselectedLabelStyle,
        child: _TabLabelBar(onPerformLayout: _saveTabOffsets, children: wrappedTabs)));

if (widget.isScrollable) {
  _scrollController ??= _TabBarScrollController(this);
  tabBar = Container(
      alignment: _alignType(widget.alignType ?? ACETabBarAlignType.center),
      child: _scrollView(tabBar));
}
tabBar = Row(children: [
  widget.startIcon ?? Container(), Flexible(child: tabBar), widget.endIcon ?? Container()
]);
return tabBar;

案例尝试

    小菜尝试在 isScrollable 是否可滑动两种状态下,在导航栏中添加左右两个固定位图标;

_tabBar05(type, isLeft, isRight, {isScrollable}) => ACETabBar(
    isScrollable: isScrollable ?? true,
    alignType: ACETabBarAlignType.left,
    startIcon: isLeft
        ? Padding(
            padding: EdgeInsets.symmetric(horizontal: 10.0),
            child: FlutterLogo()) : null,
    endIcon: isRight
        ? GestureDetector(
            onTap: () => print('----endIcon.click----'),
            child: Padding(
                padding: EdgeInsets.symmetric(horizontal: 10.0),
                child: Icon(Icons.add, color: Colors.white)))
        : null,
    controller: type == 0 ? _tabController : _tabController2,
    tabs: type == 0 ? _tabData02 : _tabData04);
    
_tabBarWid07() => Container(
    height: 200.0,
    child: Scaffold(
        appBar: AppBar(
            title: Text('true & LeftIcon & RightIcon'),
            bottom: _tabBar05(1, true, true)),
        body: _tabBarView(1)));

_tabBarWid08() => Container(
    height: 200.0,
    child: Scaffold(
        appBar: AppBar(
            title: Text('false & LeftIcon & RightIcon'),
            bottom: _tabBar05(1, true, true, isScrollable: false)),
        body: _tabBarView(1)));

小扩展

    小菜在了解 TabBar 源码过程中,简单学习了 Tab Item 以及对应 indicator 标签指标的绘制及对应的滑动过程;其中在 TabBar 绘制过程中会用到 PreferredSizeWidget 小组件;

    PreferredSizeWidget 小组件作为一个抽象接口类,主要用于返回该小部件在不受其他限制的情况下设定的较理想的大小;若没有进行约束高度,则会使用 PreferredSizeWidget 指定的高度;而 TabBar 就是实现了 preferredSize 方法,用于设置高度,小菜尝试调整 preferredSize 即可调整 TabBar 默认高度;

@override
Size get preferredSize {
  for (final Widget item in tabs) {
    if (item is Tab) {
      final Tab tab = item;
      if ((tab.text != null || tab.child != null) && tab.icon != null)
        return Size.fromHeight(_kTextAndIconTabHeight + indicatorWeight);
    }
  }
  return Size.fromHeight(_kTabHeight + indicatorWeight - 50.0);
}


    ACETabBar 案例源码


来源: 阿策小和尚
目录
相关文章
|
定位技术 开发工具 开发者
为了让外卖小哥在地图里开上火箭🚀我用FLutter自定义了地图
花了五天时间,用Flutter自定义地图是什么体验?外卖小哥都开上火箭了?什么?我被女朋友赶出家门啦?欢迎观看被女友赶出家门之开火箭送外卖篇~
|
1月前
|
运维 监控 定位技术
应用研发平台EMAS常见问题之flutter插件不支持自定义图标如何解决
应用研发平台EMAS(Enterprise Mobile Application Service)是阿里云提供的一个全栈移动应用开发平台,集成了应用开发、测试、部署、监控和运营服务;本合集旨在总结EMAS产品在应用开发和运维过程中的常见问题及解决方案,助力开发者和企业高效解决技术难题,加速移动应用的上线和稳定运行。
76 0
|
4月前
Flutter 自定义ICON库
Flutter 自定义ICON库 Flutter提供了一些内置的ICON库,但在实际开发中,可能需要一些自定义的ICON图标。Flutter允许我们使用自定义图标,本文将介绍如何创建和使用自定义ICON库。
|
4月前
|
UED
Flutter之自定义路由切换动画
Flutter之自定义路由切换动画 在Flutter中,我们可以通过Navigator来实现路由管理,包括路由的跳转和返回等。默认情况下,Flutter提供了一些简单的路由切换动画,但是有时候我们需要自定义一些特殊的动画效果来提高用户体验。本文将介绍如何在Flutter中实现自定义的路由切换动画。
|
4月前
|
开发框架 Dart 容器
Flutter 自定义渐变按钮 GradientButton
Flutter 自定义渐变按钮 GradientButton Flutter 是一种流行的跨平台移动应用开发框架。Flutter 提供了许多内置的小部件,但有时您可能需要创建自己的小部件以满足特定的需求。这个文档将介绍如何创建一个自定义渐变按钮小部件 GradientButton。
|
4月前
|
容器
Flutter 自定义实现时间轴、侧边进度条
时间轴和侧边进度条是非常常见的 UI 控件,它们可以增强应用的视觉效果和交互体验。在这篇文章中,我们将详细介绍如何使用 Flutter 自定义实现这两个控件。
|
8月前
Flutter中 解决自定义阿里妈妈图标一直显示不出来的问题
Flutter中 解决自定义阿里妈妈图标一直显示不出来的问题
64 0
|
10月前
|
Android开发 iOS开发
Flutter应用开发,系统样式改不了?SystemChrome 状态栏、导航栏、屏幕方向……想改就改
Flutter应用开发,系统样式改不了?SystemChrome 状态栏、导航栏、屏幕方向……想改就改
|
10月前
|
UED 索引
Flutter仿写微信导航栏快速实现页面导航
Flutter仿写微信导航栏快速实现页面导航
|
存储 监控
flutter系列之:如何自定义动画路由
flutter中有默认的Route组件,叫做MaterialPageRoute,一般情况下我们在flutter中进行跳转的话,只需要向Navigator中传入一个MaterialPageRoute就可以了。 但是MaterialPageRoute太普通了,如果我们想要做点不同的跳转特效应该如何处理呢? 一起来看看吧。

相关实验场景

更多