带文字的TabBar指示器
1.绘制自定义TabBar的绿色带白色文字的指示器
2.将底部灰色文字与TabrBar层叠,并调整高度位置与胶囊指示器重叠
自定义的带文字的TabBar指示器
import 'package:atui/jade/utils/JadeColors.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
class MyCustomTextIndicator extends Decoration {
final String text;
const MyCustomTextIndicator({ this.text});
BoxPainter createBoxPainter([VoidCallback onChanged]) {
return _CustomTabIndicatorPainter(text: text);
}
}
class _CustomTabIndicatorPainter extends BoxPainter {
final String text;
_CustomTabIndicatorPainter({ this.text});
void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
final rect = Rect.fromLTWH(
offset.dx - 40.w,
configuration.size.height - 60.w,
configuration.size.width + 80.w,
25,
);
final _gradientColors = [JadeColors.green_16, JadeColors.green_12];
final paint = Paint()..shader = LinearGradient(colors: _gradientColors).createShader(rect);
canvas.drawRRect(RRect.fromRectAndRadius(rect, Radius.circular(15)), paint);
final _textPainter = TextPainter(
text: TextSpan(text: text, style: TextStyle(
color: Colors.white,
fontSize: 22.sp,
fontWeight: FontWeight.bold
)),
textDirection: TextDirection.ltr,
);
_textPainter.layout();
_textPainter.paint(canvas, Offset(rect.left + (rect.width - _textPainter.width) / 2, rect.top + (rect.height - _textPainter.height) / 2));
canvas.save();
canvas.restore();
}
}
引用:
//tabBar标签tab数据
List<Map<String, dynamic>> _tabs = [
{'title': '严选', 'subTitle': '品质优选','range': 41},
{'title': '优惠', 'subTitle': '阿推优惠','range': 42},
{'title': '进口', 'subTitle': '阿推国际','range': 43},
{'title': '推享金', 'subTitle': '排行榜','range': 45},
];
_tabBar(){
return Stack(
alignment: Alignment.bottomCenter,
children: [
Padding(padding: EdgeInsets.only(bottom: 20.w),
child: Wrap(
alignment: WrapAlignment.start,
spacing: 40.w,
runSpacing: 0,
children: List.generate(_tabs.length, (index) {
return Container(
alignment: Alignment.center,
width: 124.w,
child: Text('${_tabs[index]['subTitle']}',
style: TextStyle(color: JadeColors.grey,
fontSize: 22.sp,fontWeight: FontWeight.bold),),
);
}),
)),
Container(
padding: EdgeInsets.symmetric(horizontal: 40.w),
child: TabBar(
controller: _tabController,
isScrollable: false,
labelPadding: EdgeInsets.only(left: 10,right: 10,bottom: 10.w),
indicator: MyCustomTextIndicator(text: _tabs[_currentIndex]['subTitle']),
indicatorWeight: 60.w,
labelColor: JadeColors.black,
labelStyle: TextStyle(
fontSize: 34.sp,
fontWeight: FontWeight.bold,
),
unselectedLabelColor: JadeColors.black,
unselectedLabelStyle: TextStyle(
fontSize: 34.sp,
fontWeight: FontWeight.bold,
),
indicatorSize: TabBarIndicatorSize.label,
tabs: _tabs.map((e) => Text(e['title'])).toList(),
onTap: (index) {
setState(() {
_currentIndex = index;
});
print('_currentIndex= $_currentIndex');
},
)
),
],
);
}
_tabBarView(){
return TabBarView(
controller: _tabController,
physics: const AlwaysScrollableScrollPhysics(),
children: _tabs.map((e) {
return MarketGoodsListPage(range: e['range']);
}).toList()
);
}
上弦的弧形TabBar指示器
自定义指示器
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
/*
* 自定义的上弦圆弧TabBar指示器
* */
class MyCustomArcIndicator extends Decoration {
BoxPainter createBoxPainter([VoidCallback onChanged]) {
return _CustomBoxPainter(this, onChanged);
}
}
class _CustomBoxPainter extends BoxPainter {
final MyCustomArcIndicator decoration;
_CustomBoxPainter(this.decoration, VoidCallback onChanged)
: super(onChanged);
void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
final size = configuration.size;
final newOffset = Offset(offset.dx + size.width / 2 - 10.w, size.height / 4);
var paint = Paint();
double rowHeight = 12;
paint.strokeWidth = rowHeight / 4;
paint.style = PaintingStyle.stroke;
Path path = Path();
Rect rect = Rect.fromLTWH(newOffset.dx, newOffset.dy + rowHeight / 2, rowHeight, rowHeight);
path.arcTo(rect, pi / 4,pi / 2, true);
paint.color = Color(0xFF56CEBA);
paint.strokeCap = StrokeCap.round;
paint.style = PaintingStyle.stroke;
canvas.drawPath(path, paint);
}
}
引用:
_tabBar(){
return TabBar(
isScrollable: true,
labelPadding: EdgeInsets.only(left: 10,right: 10,bottom: 10.w),
indicator: MyCustomArcIndicator(),
labelColor: JadeColors.black,
labelStyle: TextStyle(
fontSize: 36.sp,
fontWeight: FontWeight.w600,
),
unselectedLabelColor: Color(0xff333333),
unselectedLabelStyle: TextStyle(
fontSize: 36.sp,
),
indicatorSize: TabBarIndicatorSize.label,
controller: providerOf<MainModel>().tabController,
tabs: MainModel.catList().map((e) => Text(e['name'])).toList(),
onTap: (index) {
providerOf<MainModel>().currentTabIndex = index;
if(index == 7){
Provider.of<RewardPoolModel>(context, listen: false)
.searchMoneyData();
}
},
);
}
普通的TabBar自定义指示器
图1:
图2:
自定义指示器
import 'package:flutter/material.dart';
class MyCustomIndicator extends Decoration {
final double indWidth;
final double indHeight;
final double radius;
final List<Color> indicatorColor;
const MyCustomIndicator({this.indWidth = 70.0, this.indHeight = 12.0, this.radius = 5, this.indicatorColor});
BoxPainter createBoxPainter([VoidCallback onChanged]) {
return _CustomBoxPainter(this, onChanged, indWidth, indHeight, radius, indicatorColor);
}
}
class _CustomBoxPainter extends BoxPainter {
final MyCustomIndicator decoration;
final double indWidth;
final double indHeight;
final double radius;
final List<Color> indicatorColor;
_CustomBoxPainter(this.decoration, VoidCallback onChanged, this.indWidth, this.indHeight, this.radius,this.indicatorColor)
: 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();
if(indicatorColor == null || indicatorColor.isEmpty){
paint.color = Colors.yellow;
}else{
if(indicatorColor.length == 1){
paint.color = indicatorColor[0];
}else if(indicatorColor.length > 1){
paint.shader =
LinearGradient(colors: indicatorColor, begin: Alignment.centerLeft, end: Alignment.centerRight)
.createShader(rect);
}
}
paint.style = PaintingStyle.fill;
canvas.drawRRect(
RRect.fromRectAndRadius(rect, Radius.circular(radius)), // 圆角半径
paint,
);
canvas.save();
canvas.restore();
}
}
图1效果的引用:
_tabBarView(){
return Container(
color: Colors.white,
child: TabBar(
isScrollable: false,
labelPadding: EdgeInsets.symmetric(horizontal: 0),
indicator: MyCustomIndicator(indicatorColor: [Colors.yellow]),
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) {},
),
);
}
图2效果的引用:
TabBar(
tabs: tabs,
isScrollable: false,
unselectedLabelColor: const Color(0xFF000000),
labelStyle: TextStyle(fontWeight: FontWeight.bold),
labelColor: const Color(0xFF000000),
indicatorSize: TabBarIndicatorSize.label,
indicator: MyCustomIndicator(indicatorColor: [JadeColors.red,JadeColors.yellow],indHeight: 8.w,indWidth: 92.w),
controller: _tabController,
)