重庆做网站重庆做网站,wordpress主动提交百度,杭州建站模板搭建,湖南常德石门县前言#xff1a; 这几天在使用 flutter TabBar 的时候 我们的设计给我提了一个需求#xff1a; 如下 Tabbar 第一个元素 左对齐#xff0c;试了下TabBar 的配置#xff0c;无法实现这个需求#xff0c;他的 配置是针对所有元素的。而且 这个 TabBar 下面的 滑块在移动的时…前言 这几天在使用 flutter TabBar 的时候 我们的设计给我提了一个需求 如下 Tabbar 第一个元素 左对齐试了下TabBar 的配置无法实现这个需求他的 配置是针对所有元素的。而且 这个 TabBar 下面的 滑块在移动的时候 上面的文字会相应的抖动。 看了下 TabBar 的源代码 他的实现是相对复杂的 下面的 滑块是 canvas 实现的。 有可能他要实现的功能比较丰富。 自定义Tabbar 的基本布局 下面是我页面的布局这样实现起来 里面元素的 样式可以完全自己定义单个配置想怎么显示都可以。这样就可以不用局限于 自带Tabbar的配置 SingleChildScrollView 解析 完成页面布局相对简单主要实现底部 滑块的移动以及 整 SingleChildScrollView 的居中移动是一个关键点 ScrollController 中的几个关键概念 controller.position.viewportDimension SingleChildScrollView 视口 的大小position.maxScrollExtent SingleChildScrollView 可以移动的最大范围position.minScrollExtent SingleChildScrollView 可以移动最小范围 一般是0Row 的长度就是所有元素的长度之和也就是 position.maxScrollExtent position.viewportDimension Row 的长度之和 为什么是 SingleChildScrollView 最大可移动范围加 position.viewportDimension 的和 SingleChildScrollView 可见区域始终是他的视口大小不可见的也就是 Row的长度减去视口大小 也就是 maxScrollExtent 可拖动的最大区域实现 Tabbar 下面是我实现的大致效果第一个元素左对齐最后一个元素右对齐我这边是直接写死的你们封装一下 在外边直接用就好了。 代码如下 import dart:ui;import package:flutter/material.dart;
import package:game/const/app_textStyle.dart;
import package:game/utils/app_widget.dart;
import package:game/wrap/extension/extension.dart;class PageTabBar extends StatefulWidget {const PageTabBar({Key? key}) : super(key: key);overrideStatePageTabBar createState() _PageTabBarState();
}class _PageTabBarState extends StatePageTabBar {final ScrollController _controller ScrollController();int _selectIndex 0;double _width 0;double _positionX 0;final ListMap _listMap [{width: 0, name: 一号, key: GlobalKey()},{width: 0, name: 二二号技师, key: GlobalKey()},{width: 0, name: 三三三号技师, key: GlobalKey()},{width: 0, name: 四号技师, key: GlobalKey()},{width: 0, name: 五五号技师, key: GlobalKey()},{width: 0, name: 六六六号技师, key: GlobalKey()},{width: 0, name: 七号技师, key: GlobalKey()},{width: 0, name: 八八号技师, key: GlobalKey()},{width: 0, name: 九, key: GlobalKey()},{width: 0, name: 十号技师, key: GlobalKey()},];overridevoid initState() {// TODO: implement initStatesuper.initState();WidgetsBinding.instance.addPostFrameCallback((_) _printSize());// _controller.addListener(() {// print(_controller.offset:${_controller.offset});// });}overridevoid dispose() {// TODO: implement dispose_controller.dispose();super.dispose();}void _printSize() {for (Map element in _listMap) {final RenderBox box element[key].currentContext.findRenderObject();element[width] box.size.width;}_width _listMap[0][width];_selectItem(0);}overrideWidget build(BuildContext context) {return Scaffold(appBar: AppWidget.appBar(title: TabBar 测试页面),body: Center(child: Container(height: 220.cale,width: 710.cale,color: Colors.deepOrangeAccent,child: SingleChildScrollView(physics: const BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics(),),controller: _controller,scrollDirection: Axis.horizontal,child: Stack(children: [Row(children: _listMap.asMap().map((key, value) MapEntry(key,AppWidget.inkWellEffectNone(onTap: () {_selectItem(key);},child: Container(padding: key 0? EdgeInsets.only(right: 25.cale): key _listMap.length - 1? EdgeInsets.only(left: 25.cale): EdgeInsets.symmetric(horizontal: 25.cale),key: value[key],color: Colors.blue.withOpacity(0.1 * key),height: 180.cale,child: Center(child: Text(value[name],style: _selectIndex key? AppTextStyle.textStyle_34_FD3949_Bold: AppTextStyle.textStyle_30_1A1A1A,),),),),),).values.toList(),),AnimatedPositioned(bottom: 0.cale,left: _positionX,duration: const Duration(milliseconds: 250),child: AnimatedContainer(duration: const Duration(milliseconds: 250),width: _width,child: Container(height: 20.cale,margin: EdgeInsets.symmetric(horizontal: 25.cale),width: double.infinity,color: Colors.green,),),)],),),),),);}void _selectItem(int index) {print(index:$index);final ScrollPosition position _controller.position;setState(() {_selectIndex index;_width _listMap[index][width];});_positionX 0;List.generate(index, (itemIndex) {_positionX _listMap[itemIndex][width];});//当前展示的元素位置 中心点位置用户确定 滚动位置double viewPosition _positionX _listMap[index][width] / 2;double movePosition viewPosition - position.viewportDimension / 2;movePosition clampDouble(movePosition, position.minScrollExtent, position.maxScrollExtent);_controller.animateTo(movePosition,duration: const Duration(milliseconds: 300),curve: Curves.easeOut,);}
}可以按需求封装下就能上手使用了