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 createState
    return _MyPromotionListMain();
  }
}

class _MyPromotionListMain extends State<MyPromotionListMain> with TickerProviderStateMixin{

  List<String> _tabs = ['我发布的','我推享的','我的阿推码'];
  TabController _tabController;
  
  void initState() {
    // TODO: implement initState
    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 build
    return 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 createState
    return _MyPromotionListSecond();
  }
}

class _MyPromotionListSecond extends State<MyPromotionListSecond> with TickerProviderStateMixin{

  List<TabTypeMode> _tabs = [];
  TabController _tabController;

  
  void initState() {
    // TODO: implement initState
    if(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 build
    return _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);
}
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值