flutter TabBar指示器

第一层tabView

dart 复制代码
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{
  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return _MyPromotionListMain();
  }
}

class _MyPromotionListMain extends State<MyPromotionListMain> with TickerProviderStateMixin{

  List<String> _tabs = ['我发布的','我推享的','我的阿推码'];
  TabController _tabController;
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    _tabController = TabController(
       // initialIndex: widget.initialIndex??0,
        length: _tabs.length,vsync: this);
  }

  @override
  void dispose() {
    // TODO: implement dispose
    _tabController.dispose();
    super.dispose();
  }
  @override
  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

dart 复制代码
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({@required this.type});

  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return _MyPromotionListSecond();
  }
}

class _MyPromotionListSecond extends State<MyPromotionListSecond> with TickerProviderStateMixin{

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

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

  @override
  void dispose() {
    // TODO: implement dispose
    _tabController.dispose();
    super.dispose();
  }

  @override
  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()
    );
  }
}

指示器:

dart 复制代码
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});

  @override
  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);

  @override
  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);

}

}

相关推荐
江上清风山间明月12 小时前
Flutter开发的应用页面非常多时如何高效管理路由
android·flutter·路由·页面管理·routes·ongenerateroute
Zsnoin能1 天前
flutter国际化、主题配置、视频播放器UI、扫码功能、水波纹问题
flutter
早起的年轻人1 天前
Flutter CupertinoNavigationBar iOS 风格导航栏的组件
flutter·ios
HappyAcmen1 天前
关于Flutter前端面试题及其答案解析
前端·flutter
coooliang1 天前
Flutter 中的单例模式
javascript·flutter·单例模式
coooliang1 天前
Flutter项目中设置安卓启动页
android·flutter
JIngles1231 天前
flutter将utf-8编码的字节序列转换为中英文字符串
java·javascript·flutter
B.-1 天前
在 Flutter 中实现文件读写
开发语言·学习·flutter·android studio·xcode
freflying11192 天前
使用jenkins构建Android+Flutter项目依赖自动升级带来兼容性问题及Jenkins构建速度慢问题解决
android·flutter·jenkins
机器瓦力2 天前
Flutter应用开发:对象存储管理图片
flutter