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 案例源码


来源: 阿策小和尚
目录
相关文章
|
4天前
|
前端开发 搜索推荐 开发者
【Flutter前端技术开发专栏】Flutter中的自定义主题与暗黑模式
【4月更文挑战第30天】本文介绍了如何在Flutter中自定义主题和实现暗黑模式。通过`ThemeData`类定义应用的外观,包括颜色、字体和样式。示例展示了如何设置主色、强调色及文本、按钮主题。暗黑模式可通过`darkTheme`属性启用,结合`ThemeData.dark()`方法定制。利用`MediaQuery`监听系统亮度变化,动态调整暗黑模式状态。Flutter的这些特性有助于开发者创建独特且用户友好的界面。
【Flutter前端技术开发专栏】Flutter中的自定义主题与暗黑模式
|
4天前
|
缓存 前端开发 搜索推荐
【Flutter前端技术开发专栏】Flutter中的自定义绘制与Canvas API
【4月更文挑战第30天】Flutter允许开发者通过`CustomPaint`和`CustomPainter`进行自定义绘制,以实现丰富视觉效果。`CustomPaint` widget将`CustomPainter`应用到画布,而`CustomPainter`需实现`paint`和`shouldRepaint`方法。`paint`用于绘制图形,如示例中创建的`MyCirclePainter`绘制蓝色圆圈。Canvas API提供绘制形状、路径、文本和图片等功能。注意性能优化,避免不必要的重绘和利用缓存提升效率。自定义绘制让Flutter UI更具灵活性和个性化,但也需要图形学知识和性能意识。
【Flutter前端技术开发专栏】Flutter中的自定义绘制与Canvas API
|
4天前
|
开发框架 前端开发 搜索推荐
【Flutter前端技术开发专栏】Flutter中的自定义Widget与渲染流程
【4月更文挑战第30天】探索Flutter的自定义Widget与渲染流程。自定义Widget是实现复杂UI设计的关键,优点在于个性化设计、功能扩展和代码复用,但也面临性能优化和复杂性管理的挑战。创建步骤包括设计结构、定义Widget类、实现构建逻辑和处理交互。Flutter渲染流程涉及渲染对象树、布局、绘制和合成阶段。实践案例展示如何创建带渐变背景和阴影的自定义按钮。了解这些知识能提升应用体验并应对开发挑战。查阅官方文档以深入学习。
【Flutter前端技术开发专栏】Flutter中的自定义Widget与渲染流程
|
4天前
|
前端开发 开发者 UED
Flutter的自定义Painter:深入探索自定义绘制Widget的技术实现
【4月更文挑战第26天】Flutter的自定义Painter允许开发者根据需求绘制独特UI,通过继承`CustomPaint`类和重写`paint`方法实现。在`paint`中使用`Canvas`绘制图形、路径等。创建自定义Painter类后,将其作为`CustomPaint` Widget的`painter`属性使用。此技术可实现自定义形状、渐变、动画等复杂效果,提升应用视觉体验。随着Flutter的进化,自定义Painter将提供更丰富的功能。
|
4天前
|
运维 监控 定位技术
应用研发平台EMAS常见问题之flutter插件不支持自定义图标如何解决
应用研发平台EMAS(Enterprise Mobile Application Service)是阿里云提供的一个全栈移动应用开发平台,集成了应用开发、测试、部署、监控和运营服务;本合集旨在总结EMAS产品在应用开发和运维过程中的常见问题及解决方案,助力开发者和企业高效解决技术难题,加速移动应用的上线和稳定运行。
81 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 自定义实现这两个控件。
111 1
|
4天前
|
开发框架
Flutter自定义对话框返回相关问题汇总
Flutter自定义对话框返回相关问题汇总,详细解释 Flutter是一款流行的移动应用开发框架,它提供了很多内置的对话框,但是有时候我们需要自定义对话框来满足特定需求。在使用自定义对话框时,可能会遇到一些问题,下面是一些常见问题的解答: