当前位置: 首页 > article >正文

flutter TabBar自定义指示器(带文字的指示器、上弦弧形指示器、条形背景指示器、渐变色的指示器)

带文字的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,
              )

http://www.kler.cn/news/358672.html

相关文章:

  • Atlas800昇腾服务器(型号:3000)—YOLO全系列NPU推理【检测】(五)
  • Navicat连接openGauss数据库详细指南
  • Vue3在大数据场景下原生实现单元格合并,让Thead固定让Tbody滚动
  • Linux——传输层协议
  • vscode 远程linux服务器 连接git
  • 陈文自媒体:小红书,24小时爆99+的秘诀!
  • 视觉检测解决方案
  • 3D Slicer 教程三 ---- 坐标系
  • 小技巧——如何启动miivii控制器自带相机demo
  • 单细胞分析 | Cicero+Signac 寻找顺式共可及网络
  • c#webapi远程调试方法asp.netcore
  • 【思维导图】C语言
  • 【C语言】指针进阶【万字详细版】
  • 使用langchain和大模型API提取QA的实战教程
  • RHEL: rpm2cpio: signature hdr data: BAD, no. of bytes(19987) out of range
  • 【基于Spring Boot+Unipp的古诗词学习小程序【原创】
  • lazyLoad
  • 【java数据结构】栈
  • SQL Server LocalDB 表数据中文乱码问题
  • java 获取最高20%数据