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);
}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/196121.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Nacos】配置管理、微服务配置拉取、实现配置热更新、多环境配置

&#x1f40c;个人主页&#xff1a; &#x1f40c; 叶落闲庭 &#x1f4a8;我的专栏&#xff1a;&#x1f4a8; c语言 数据结构 javaEE 操作系统 Redis 石可破也&#xff0c;而不可夺坚&#xff1b;丹可磨也&#xff0c;而不可夺赤。 Nacos 一、nacos实现配置管理1.1 统一配置管…

Windows11 python3.12 安装pyqt6 pyqt6-tools

Windows11 python3.12 安装pyqt6比较容易&#xff0c;但pyqt6-tools一直安装不上去。出错信息如下&#xff1a; (venv) PS D:\python_project\pyqt6> pip install pyqt6-tools Collecting pyqt6-toolsUsing cached pyqt6_tools-6.4.2.3.3-py3-none-any.whl (29 kB) Collec…

cp: can‘t stat ‘/usr/share/zoneinfo/Asia/Shanghai‘: No such file or directory

目录 问题描述问题分析解决方案容器时区验证 问题描述 使用下面的 Dockerfile 为 youlai-boot 项目制作镜像设置容器时区报错。 # 基础镜像 FROM openjdk:17-jdk-alpine # 时区修改 RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \&& echo Asia/Sha…

【图数据库实战】HugeGraph架构

一、概述 作为一款通用的图数据库产品&#xff0c;HugeGraph需具备图数据的基本功能&#xff0c;如下图所示。HugeGraph包括三个层次的功能&#xff0c;分别是存储层、计算层和用户接口层。 HugeGraph支持OLTP和OLAP两种图计算类型&#xff0c;其中OLTP实现了Apache TinkerPop3…

深度学习到智能小车(1)深度学习框架

0.前提 最近新开了一门叫机器学习的课程&#xff0c;老师一直在跟我们讲一些有关这方面的知识&#xff0c;告诉我们一定要学好数学&#xff0c;因为数学是算法的基础。我手上的donkeycar刚好也涉及到Keras深度神经网络&#xff0c;所以出于好奇我去图书馆借回了一本叫《Keras深…

DevSeo Studio设置中文界面

安装好DevSeo Studio后默认打开是欢迎页。 左下角Configure点击展开&#xff0c;选择plugins 弹出页面选择“installed”,然后输入chinese,默认是关闭的&#xff0c;点击enable将它启用&#xff0c;然后点击OK。 弹出页面点击“restart”重启即可。

VS中修改解决方案名称和项目名称

如何修改visual studio2019中的项目名 - 知乎 (zhihu.com) 查了很多&#xff0c;还是这个可行。虽然文中说不是最简单的&#xff0c;但在所查找资料中是可行且最简单的。 要点主要是&#xff1a; 1、比如我们复制一个解决方案&#xff0c;最好是带代码哈&#xff0c;也就是添…

2023.11.18 Hadoop之 YARN

1.简介 Apache Hadoop YARN &#xff08;Yet Another Resource Negotiator&#xff0c;另一种资源协调者&#xff09;是一种新的 Hadoop 资源管理器&#xff0c;它是一个通用资源管理系统和调度平台&#xff0c;可为上层应用提供统一的资源管理和调度。支持多个数据处理框架&…

Springboot+vue的学生成绩管理系统(有报告),Javaee项目,springboot vue前后端分离项目。

演示视频&#xff1a; Springbootvue的学生成绩管理系统&#xff08;有报告&#xff09;&#xff0c;Javaee项目&#xff0c;springboot vue前后端分离项目。 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家…

Docker的3主3从redis集群配置(扩容和缩容配置)

3主3从redis集群配置 1、关闭防火墙启动docker后台服务 systemctl start docker2、新建6个docker容器redis实例 docker run -d --name redis-node-1 --net host --privilegedtrue -v /data/redis/share/redis-node-1:/data redis:6.0.8 --cluster-enabled yes --appendonly …

MatLab的下载、安装与使用(亲测有效)

1、概述 MatLab是由MathWorks公司开发并发布的&#xff0c;支持线性代数、矩阵运算、绘制函数和数据、信号处理、图像处理以及视频处理等功能。广泛用于算法开发、数据可视化、数据分析以及数值计算等。 Matlab 的主要特性包括&#xff1a; 简单易用的语法&#xff0c;使得程…

4-flask-cbv源码、Jinja2模板、请求响应、flask中的session、flask项目参考

1 flask中cbv源码 2 Jinja2模板 3 请求响应 4 flask中的session 5 flask项目参考 1 flask中cbv源码 ***flask的官网文档&#xff1a;***https://flask.palletsprojects.com/en/3.0.x/views/1 cbv源码执行流程1 请求来了&#xff0c;路由匹配成功---》执行ItemAPI.as_view(item…

PS学习笔记——新建文档/修改文档

文章目录 新建文档文档属性像素/分辨率颜色模式背景内容高级选项存储预设 修改文档 新建文档 方法一&#xff1a;ctrlN快捷键可直接打开新建文档界面 方法二&#xff1a;点击菜单栏中 文件->新建&#xff0c;即可打开新建文档界面 文档参数可按需调节(标题可以提前设定或者…

【精选】HTML5最全知识点集合

HTML5简介与基础骨架 HTML5介绍 HTML5是用来描述网页的一种语言&#xff0c;被称为超文本标记语言。用HTML5编写的文件&#xff0c;后缀以.html结尾 HTML是一种标记语言&#xff0c;标记语言是一套标记标签。标签是由尖括号包围的关键字&#xff0c;例如&#xff1a;<html…

go语言 | 图解字节青训营抖音(一)

前言 本文大致介绍了本人及本人所在小组为第五届字节跳动青训营后端专场大项目需求 —— 「实现一个极简版抖音」的部分实现细节。 需求 本届后端青训营大项目要求实现一个极简版抖音的后端服务&#xff0c;该后端服务通过 HTTP 协议向已被设计好的前端 App 传递数据&#xf…

服务器数据恢复—热备盘同步中断导致Raid5数据丢失的数据恢复案例

服务器数据恢复环境&#xff1a; 某单位一台服务器上有一组raid5阵列&#xff0c;该raid5阵列有15块成员盘。上层是一个xfs裸分区&#xff0c;起始位置是0扇区。 服务器故障&检测&#xff1a; 服务器raid5阵列中有硬盘性能表现不稳定&#xff0c;但是由于管理员长时间没有关…

11.5MyBatis(进阶)

一.${}和#{} 1.$是直接替换,#是预处理(使用占位符,替换成?).前者不安全(SQL注入), 后者安全. 2.$的使用场景: 如果传递的值是sql的关键字,只能使用$,不能使用#(asc,desc). 二.SQL注入 注意: 如果使用${}进行传参,一定要是可以穷举的,并且要进行安全性验证(例如排序,只能传a…

Leetcode_48:旋转图像

题目描述&#xff1a; 给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在 原地 旋转图像&#xff0c;这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3],…

Springboot更新用户头像

人们通常(为徒省事)把一个包含了修改后userName的完整userInfo对象传给后端&#xff0c;做完整更新。但仔细想想&#xff0c;这种做法感觉有点二&#xff0c;而且浪费带宽。 于是patch诞生&#xff0c;只传一个userName到指定资源去&#xff0c;表示该请求是一个局部更新&#…

2023.11.16 hivesql高阶函数之json

目录 1.数据准备 2.操作 -- 方式1: 逐个(字段)处理, get_json_object UDF函数 最大弊端是一次只能解析提取一个字段 -- 方式2: 逐条处理. json_tuple 这是一个UDTF函数 可以一次解析提取多个字段 -- 方式3: 在建表时候, 直接处理json, row format SerDe 能处理Json的SerDe类…