flutter TabBar指示器

第一层tabView
import 'package:jade/configs/PathConfig.dart';
import 'package:jade/customWidget/MyCustomIndicator.dart';
import'package:jade/homePage/promotion/promotionPost/MyPromotionListMainDesc.dart';
import 'package:jade/homePage/promotion/promotionPost/MyPromotionListSecond.dart';
import 'package:atui/jade/utils/JadeColors.dart';
import 'package:atui/util/navigator_util.dart';
import 'package:atui/widget/custom_appbar.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';class MyPromotionListMain extends StatefulWidget{State<StatefulWidget> createState() {// TODO: implement createStatereturn _MyPromotionListMain();}
}class _MyPromotionListMain extends State<MyPromotionListMain> with TickerProviderStateMixin{List<String> _tabs = ['我发布的','我推享的','我的阿推码'];TabController _tabController;void initState() {// TODO: implement initStatesuper.initState();_tabController = TabController(// initialIndex: widget.initialIndex??0,length: _tabs.length,vsync: this);}void dispose() {// TODO: implement dispose_tabController.dispose();super.dispose();}Widget build(BuildContext context) {// TODO: implement buildreturn Scaffold(backgroundColor: Colors.white,appBar: CustomAppBar(backgroundColor: Colors.white,elevation: 0,leading: GestureDetector(onTap: () {Navigator.pop(context);},child: Icon(Icons.arrow_back_ios),),iconTheme: IconThemeData(color: Color(0xff999999)),title: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween,children: [Container(),Container(margin: EdgeInsets.only(right: 34.w),child: Text('推享赚',style: TextStyle(color: Colors.black),),),GestureDetector(child: Container(color: Colors.transparent,padding: EdgeInsets.all(4),child: Image.asset(PathConfig.iconQuestion,height: 40.w),),onTap: () {NavigatorUtil.push(MyPromotionListMainDesc());},)],),centerTitle: true,),body: _body());}_body(){return Column(children: [_tabBarView(),Container(height: 2.w,width: double.infinity,color: JadeColors.lightGrey,margin: EdgeInsets.symmetric(vertical: 20.w),),Expanded(child: _tabView())],);}_tabBarView(){return TabBar(isScrollable: false,labelPadding: EdgeInsets.symmetric(horizontal: 0),indicator: MyCustomIndicator(),labelColor: Color(0xff333333),labelStyle: TextStyle(fontSize: 30.sp,fontWeight: FontWeight.w600,),unselectedLabelColor: JadeColors.grey,unselectedLabelStyle: TextStyle(fontSize: 30.sp,fontWeight: FontWeight.w300),indicatorSize: TabBarIndicatorSize.label,controller: _tabController,tabs: _tabs.map((value) => Container(padding: EdgeInsets.symmetric(horizontal: 20.w),child: Text(value))).toList(),onTap: (index) {},);}_tabView(){return TabBarView(//physics: const NeverScrollableScrollPhysics(),controller: _tabController,children: [MyPromotionListSecond(type: 0),MyPromotionListSecond(type: 1),MyPromotionListSecond(type: 2)]);}
}
第二层tabView
import 'package:-jade/homePage/promotion/promotionPost/MyPromotionList.dart';
import 'package:jade/utils/JadeColors.dart';
import 'package:util/tab/customize_dicator.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';/*
* 状态这一级的tabBar页面
* */class TabTypeMode {int status;String title;TabTypeMode({this.status,this.title,});
}class MyPromotionListSecond extends StatefulWidget{final int type; //0我发布的 1我推享的 2我的阿推码const MyPromotionListSecond({ this.type});State<StatefulWidget> createState() {// TODO: implement createStatereturn _MyPromotionListSecond();}
}class _MyPromotionListSecond extends State<MyPromotionListSecond> with TickerProviderStateMixin{List<TabTypeMode> _tabs = [];TabController _tabController;void initState() {// TODO: implement initStateif(widget.type == 2){_tabs = [TabTypeMode(status: 0,title: '全部'),TabTypeMode(status: 1,title: '待使用'),TabTypeMode(status: 2,title: '已使用'),TabTypeMode(status: 3,title: '已失效')];}else{_tabs = [TabTypeMode(status: 0,title: '全部'),TabTypeMode(status: 1,title: '进行中'),TabTypeMode(status: 2,title: '已结束')];}super.initState();_tabController = TabController(// initialIndex: widget.initialIndex??0,length: _tabs.length,vsync: this);}void dispose() {// TODO: implement dispose_tabController.dispose();super.dispose();}Widget build(BuildContext context) {// TODO: implement buildreturn _body();}_body(){return Column(children: [Container(margin: EdgeInsets.only(bottom: 20.w),alignment: Alignment.centerLeft,child: _tabBarView(),),Expanded(child: _tabView())],);}_tabBarView(){return TabBar(isScrollable: true,labelPadding: EdgeInsets.symmetric(horizontal: 0),indicator: MyUnderlineTabIndicator(borderSide:BorderSide(width: 2, color: JadeColors.yellow),insets: EdgeInsets.only(bottom: 5)),labelColor: Color(0xff333333),labelStyle: TextStyle(fontSize: 30.sp,fontWeight: FontWeight.w600,),unselectedLabelColor: JadeColors.grey,unselectedLabelStyle: TextStyle(fontSize: 30.sp,fontWeight: FontWeight.w300),indicatorWeight: 20.w,indicatorSize: TabBarIndicatorSize.label,controller: _tabController,tabs: _tabs.map((value) => Container(padding: EdgeInsets.symmetric(horizontal: 20.w),child: Text(value.title))).toList(),onTap: (index) {},);}_tabView(){return TabBarView(//physics: const NeverScrollableScrollPhysics(),controller: _tabController,children: _tabs.map((value) {return MyPromotionList(widget.type,value.status);}).toList());}
}
指示器:
import 'package:flutter/material.dart';class MyCustomIndicator extends Decoration {final double indWidth;final double indHeight;final double radius;MyCustomIndicator({this.indWidth = 70.0, this.indHeight = 12.0, this.radius = 5});BoxPainter createBoxPainter([VoidCallback onChanged]) {return _CustomBoxPainter(this, onChanged, indWidth, indHeight, radius);}
}class _CustomBoxPainter extends BoxPainter {final MyCustomIndicator decoration;final double indWidth;final double indHeight;final double radius;_CustomBoxPainter(this.decoration, VoidCallback onChanged, this.indWidth, this.indHeight, this.radius): super(onChanged);void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {final size = configuration.size;final newOffset = Offset(offset.dx + (size.width - indWidth) / 2, size.height - indHeight);final Rect rect = newOffset & Size(indWidth, indHeight);final Paint paint = Paint();paint.color = Colors.yellow;paint.style = PaintingStyle.fill;canvas.drawRRect(RRect.fromRectAndRadius(rect, Radius.circular(radius)), // 圆角半径paint,);}
}
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import ‘package:flutter/material.dart’;
import ‘package:flutter/widgets.dart’;
/// Used with [TabBar.indicator] to draw a horizontal line below the
/// selected tab.
///
/// The selected tab underline is inset from the tab’s boundary by [insets].
/// The [borderSide] defines the line’s color and weight.
///
/// The [TabBar.indicatorSize] property can be used to define the indicator’s
/// bounds in terms of its (centered) widget with [TabIndicatorSize.label],
/// or the entire tab with [TabIndicatorSize.tab].
class MyUnderlineTabIndicator extends Decoration {
/// Create an underline style selected tab indicator.
///
/// The [borderSide] and [insets] arguments must not be null.
const MyUnderlineTabIndicator({
this.borderSide = const BorderSide(width: 2.0, color: Colors.white),
this.insets = EdgeInsets.zero,
}) : assert(borderSide != null),
assert(insets != null);
/// The color and weight of the horizontal line drawn below the selected tab.
final BorderSide borderSide;
/// Locates the selected tab’s underline relative to the tab’s boundary.
///
/// The [TabBar.indicatorSize] property can be used to define the
/// tab indicator’s bounds in terms of its (centered) tab widget with
/// [TabIndicatorSize.label], or the entire tab with [TabIndicatorSize.tab].
final EdgeInsetsGeometry insets;
@override
Decoration lerpFrom(Decoration a, double t) {
if (a is UnderlineTabIndicator) {
return UnderlineTabIndicator(
borderSide: BorderSide.lerp(a.borderSide, borderSide, t),
insets: EdgeInsetsGeometry.lerp(a.insets, insets, t),
);
}
return super.lerpFrom(a, t);
}
@override
Decoration lerpTo(Decoration b, double t) {
if (b is MyUnderlineTabIndicator) {
return MyUnderlineTabIndicator(
borderSide: BorderSide.lerp(borderSide, b.borderSide, t),
insets: EdgeInsetsGeometry.lerp(insets, b.insets, t),
);
}
return super.lerpTo(b, t);
}
@override
_MyUnderlinePainter createBoxPainter([ VoidCallback onChanged ]) {
return _MyUnderlinePainter(this, onChanged);
}
}
class _MyUnderlinePainter extends BoxPainter {
_MyUnderlinePainter(this.decoration, VoidCallback onChanged)
: assert(decoration != null),
super(onChanged);
final MyUnderlineTabIndicator decoration;
BorderSide get borderSide => decoration.borderSide;
EdgeInsetsGeometry get insets => decoration.insets;
Rect _indicatorRectFor(Rect rect, TextDirection textDirection) {
assert(rect != null);
assert(textDirection != null);
final Rect indicator = insets.resolve(textDirection).deflateRect(rect);
//希望的宽度
double wantWidth = 14;
//取中间坐标
double cw = (indicator.left + indicator.right) / 2;
return Rect.fromLTWH(cw - wantWidth / 2,indicator.bottom - borderSide.width, wantWidth, borderSide.width);
}
@override
void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
assert(configuration != null);
assert(configuration.size != null);
final Rect rect = offset & configuration.size;
final TextDirection textDirection = configuration.textDirection;
final Rect indicator = _indicatorRectFor(rect, textDirection).deflate(borderSide.width / 2.0);
// final Paint paint = borderSide.toPaint()…strokeCap = StrokeCap.square;
// 改为圆角
final Paint paint = borderSide.toPaint()…strokeCap = StrokeCap.round;
canvas.drawLine(indicator.bottomLeft, indicator.bottomRight, paint);
}
}
相关文章:
flutter TabBar指示器
第一层tabView import package:jade/configs/PathConfig.dart; import package:jade/customWidget/MyCustomIndicator.dart; importpackage:jade/homePage/promotion/promotionPost/MyPromotionListMainDesc.dart; import package:jade/homePage/promotion/promotionPost/MyPr…...
PDF/X、PDF/A、PDF/E:有什么区别,为什么有这么多格式?
PDF 是一种通用文件格式,允许用户演示和共享文档,无论软件、硬件或操作系统如何。多年来,已经创建了多种 PDF 子类型来满足各个行业的不同需求。让我们看看一些最流行的格式:PDF/X、PDF/A 和 PDF/E。 FastReport .net下载 PDF/X …...
Microsoft发布了一份关于其产品安全修复的 11 月报告。
👾 平均每天有 50 多个漏洞被发现,其中一些会立即被网络犯罪分子利用。我们把那些现在很受网络犯罪分子欢迎,或者根据我们的预测,在不久的将来可能会被大量利用的漏洞称为趋势漏洞。 在攻击者开始利用这些漏洞之前 12 小时&#…...
12v24v60v高校同步降压转换芯片推荐
12V/24V/60V 高校同步降压转换芯片推荐: 对于需要高效、稳定、低噪音的降压转换芯片,推荐使用WD5030E和WD5105。这两款芯片都是采用同步整流技术,具有高效率、低噪音、低功耗等优点,适用于各种电子设备。 WD5030E是一款高效率…...
pip 问题
升级pip命令: python -m pip install --upgrade pippip不能下载pytorch: 这个问题我一直没解决。不知道有哪位大佬可以留言给我。把whl文件下载到本地也没有,pip不会进行本地文件夹搜索。...
云计算(一):弹性计算概述
云计算(一):弹性计算概述 背景含义原理应用 背景 在实际场景中,经常会出现短时间内资源需求爆发式增长或长时间内资源需求不断增长,这时需要资源供给时刻满足需求的变化,保障业务正常运行。传统的供给方式…...
Qt/C++ 获取QProcess启动的第三方软件的窗体标题
Qt/C 获取QProcess启动的第三方软件的窗体标题,在使用EnumWindows获取窗体句柄(HWND)时,如果返回提前FALSE,则获取到的HWND状态IsWindow正常,但就是获取不到窗体标题。必须正常返回TRUE才能使用HWND获取到窗体标题,要不…...
Borland编辑器DOS系统快捷键应用
在项目中接触到DOS系统,该系统距离当下已经接近20年时间,网络上资源较少,因为需要用到C语言编辑器BorlandC,每次应用时难免会忘记快捷键使用,给使用造成很大的不便。 于是把现有收集的快捷键做出整理便于使用,供大家参…...
KeyarchOS的CentOS迁移实践:使用操作系统迁移工具X2Keyarch V2.0
KeyarchOS的CentOS迁移实践:使用操作系统迁移工具X2Keyarch V2.0 作者: 猫头虎博主 文章目录 KeyarchOS的CentOS迁移实践:使用操作系统迁移工具X2Keyarch V2.0🐅摘要引言1. 迁移前的精心准备1.1 系统环境介绍1.2 深度数据验证1.2.…...
Golang抓包:实现网络数据包捕获与分析
介绍 在网络通信中,网络数据包是信息传递的基本单位。抓包是一种监控和分析网络流量的方法,用于获取网络数据包并对其进行分析。在Golang中,我们可以借助现有的库来实现抓包功能,进一步对网络数据进行分析和处理。 本文将介绍如…...
分类预测 | Matlab实现QPSO-SVM、PSO-SVM、SVM多特征分类预测对比
分类预测 | Matlab实现QPSO-SVM、PSO-SVM、SVM多特征分类预测对比 目录 分类预测 | Matlab实现QPSO-SVM、PSO-SVM、SVM多特征分类预测对比分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matlab实现QPSO-SVM、PSO-SVM、SVM分类预测对比,运行环境Matlab2018b…...
kubernetes部署jenkins
参考:kubernetes 部署 Jenkins jenkins kubernetes pipeline_mob64ca14116c53的技术博客_51CTO博客 第七篇:kubernetes部署jenkins-CSDN博客 1、当前kubernetes集群已部署nfs服务 showmount -e 创建jenkins目录 2、添加jenkins的pvc kubectl create …...
Node.js详解
一、是什么 Node.js 是一个开源与跨平台的 JavaScript 运行时环境 在浏览器外运行 V8 JavaScript 引擎(Google Chrome 的内核),利用事件驱动、非阻塞和异步输入输出模型等技术提高性能 可以理解为 Node.js 就是一个服务器端的、非阻塞式I/…...
v-html命令渲染的内容,使用scoped属性的情况下,样式不起作用
v-html命令渲染的内容,使用scoped属性的情况下,样式不起作用 如: CSS: <style scoped> .question_title_text img{ display: block; height: 200px; margin: 10px auto 0 auto;} </style> HTML: <d…...
浅谈vue2.0和vue3.0的区别
Vue3.0相对于Vue2.0有以下改进: Vue 3.0 是一个新版本的 Vue.js,它提供了更高效的渲染性能和更强大的工具链。下面是一些 Vue 3.0 的具体用法: 创建 Vue 实例:与 Vue 2.x 相同,使用 Vue.createApp() 方法创建 Vue 实例…...
git clone报错SSL connect error
解决CentOS 6.6上Git操作引发的SSL连接错误问题 最近在处理一个CentOS 6.6服务器上的问题时,遇到了一个比较棘手的问题。我的小伙伴在操作Git时,发现无法执行git pull命令,提示找不到Git组件。在这篇文章中,我会详细介绍我们是如…...
LeetCode(26)判断子序列【双指针】【简单】
目录 1.题目2.答案3.提交结果截图 链接: 判断子序列 1.题目 给定字符串 s 和 t ,判断 s 是否为 t 的子序列。 字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(…...
学习c#的第十五天
目录 C# 预处理器指令 C# 预处理器指令列表 #define 预处理器 条件指令 #warning 和 #error #region 和 #endregion #line #pragma C# 预处理器指令 预处理器指令指导编译器在实际编译开始之前对信息进行预处理。 所有的预处理器指令都是以 # 开始。且在一行上&#…...
TrafficGPT: Viewing, Processing, and Interacting with Traffic Foundation Models
这篇论文的标题是“TrafficGPT: Viewing, Processing, and Interacting with Traffic Foundation Models”,它探讨了将大型语言模型(如ChatGPT)与交通基础模型结合的潜力和应用。主要内容包括: 论文背景:论文指出&…...
SPASS-参数估计与假设检验
参数估计 点估计 点估计用样本统计量的值直接作为总体参数的估计值。如用样本均值直接作为总体均值的估计值,用样本方差直接作为总体方差的估计值等。 常用的点估计法 (1)矩估计法 (2)极大似然估计法 (3)稳健估计法 区间估计 因为点估计直接用样本估计值作为总体参数…...
Clawdbot整合Qwen3:32B效果体验:长文档理解与精准问答演示
Clawdbot整合Qwen3:32B效果体验:长文档理解与精准问答演示 1. 从痛点出发:为什么你需要这个工具 如果你经常需要处理技术文档、合同、论文或者产品手册,一定遇到过这样的困扰:面对一份几十页甚至上百页的PDF文件,想要…...
基于H5的初学开发
目标: 1.能搭出页面 2.能看懂基本标签 3.能做表单 4.能放图片、音频、视频 5.能做简单画布效果 6.能做一个 AI Photo Booth 静态演示页 7.每个实验做完都能看到结果,不容易卡死 开发工具:VS Cod 本实验覆盖哪些 H5 内容 1.h…...
Dynamic Deep Learning for Li-ion Battery Fault Detection: A Practical Approach with Real-world EV Da
1. 动态深度学习在锂电池故障检测中的核心价值 锂电池作为电动汽车的核心部件,其健康状况直接关系到整车的安全性和可靠性。传统基于阈值的检测方法在面对复杂多变的实际工况时,往往表现不佳。我们团队在实际测试中发现,某品牌车辆在低温环境…...
Z-Image-Turbo在艺术创作中的实战:将文字灵感转化为超写实画作
Z-Image-Turbo在艺术创作中的实战:将文字灵感转化为超写实画作 你是否曾经有过绝妙的创意画面,却苦于无法将其具现化?Z-Image-Turbo极速云端创作室正是为解决这一痛点而生。这个基于先进AI技术的文生图工具,能够将你的文字描述在…...
大麦智能抢票系统:告别手速极限的终极解决方案
大麦智能抢票系统:告别手速极限的终极解决方案 【免费下载链接】ticket-purchase 大麦自动抢票,支持人员、城市、日期场次、价格选择 项目地址: https://gitcode.com/GitHub_Trending/ti/ticket-purchase 还在为抢不到热门演唱会门票而烦恼吗&…...
利用快马平台快速构建技能评估系统原型:以skill-vetter为例
利用快马平台快速构建技能评估系统原型:以skill-vetter为例 最近在做一个前端开发技能评估系统,需要快速验证产品原型。传统开发流程从搭建环境到功能实现至少需要1-2周,但通过InsCode(快马)平台的AI辅助和现成模板,我只用了3天就…...
ESP32S3-Cam + MPU6050 DMP移植避坑实录:从编译报错到姿态数据稳定输出的完整流程
ESP32S3-Cam与MPU6050 DMP移植实战:从编译报错到稳定姿态解算的全流程解析 当ESP32S3-Cam遇上MPU6050的DMP(数字运动处理器)功能,本应是物联网项目中实现低成本姿态检测的完美组合。但实际移植过程中,开发者往往会遭遇…...
Fish Speech 1.5开源可部署:模型权重分离存储与热更新机制设计
Fish Speech 1.5开源可部署:模型权重分离存储与热更新机制设计 1. 引言:语音合成的新突破 当你听到一段自然流畅的语音,是否曾想过它可能完全由AI生成?Fish Speech 1.5正是这样一个令人惊叹的技术成果——它能够仅凭10-30秒的参…...
RTK定位从入门到实践:如何利用千寻服务和Ntrip协议,让你的无人机定位精度达到厘米级?
RTK定位从入门到实践:如何利用千寻服务和Ntrip协议实现厘米级无人机定位 当无人机在农田上方悬停时,1米的定位误差可能导致农药喷洒完全错过目标作物;当测绘无人机进行地形扫描时,几厘米的高度误差可能使整个3D建模数据失效。这就…...
视觉问答技术全解析:从原理到实践的LAVIS框架应用指南
视觉问答技术全解析:从原理到实践的LAVIS框架应用指南 【免费下载链接】LAVIS LAVIS - A One-stop Library for Language-Vision Intelligence 项目地址: https://gitcode.com/gh_mirrors/la/LAVIS 技术原理:机器如何"看懂"并"回答…...
