|
|
@@ -1,26 +1,23 @@
|
|
|
+import 'dart:ui';
|
|
|
+
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
|
|
/// 自定义Tab的指示器
|
|
|
class CustomTabIndicator extends Decoration {
|
|
|
- /// Create an underline style selected tab indicator.
|
|
|
- ///
|
|
|
- /// The [borderSide] and [insets] arguments must not be null.
|
|
|
const CustomTabIndicator({
|
|
|
+ // 指示器的宽度
|
|
|
this.width = 20,
|
|
|
+ // 指示器的形状,默认为圆角
|
|
|
this.strokeCap = StrokeCap.round,
|
|
|
+ // 指示器的高度和纯颜色,渐变色优先于这里的纯颜色
|
|
|
this.borderSide = const BorderSide(width: 2.0, color: Colors.white),
|
|
|
+ // 指示器距离Tab的外边距
|
|
|
this.insets = EdgeInsets.zero,
|
|
|
+ // 渐变色
|
|
|
+ this.gradient,
|
|
|
});
|
|
|
|
|
|
- /// 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
|
|
|
- /// [TabBarIndicatorSize.label], or the entire tab with
|
|
|
- /// [TabBarIndicatorSize.tab].
|
|
|
final EdgeInsetsGeometry insets;
|
|
|
|
|
|
/// 新增属性:控制器宽度
|
|
|
@@ -29,12 +26,18 @@ class CustomTabIndicator extends Decoration {
|
|
|
/// 新增属性:控制器边角形状
|
|
|
final StrokeCap strokeCap;
|
|
|
|
|
|
+ /// 新增属性:渐变色
|
|
|
+ final Gradient? gradient;
|
|
|
+
|
|
|
@override
|
|
|
Decoration? lerpFrom(Decoration? a, double t) {
|
|
|
if (a is CustomTabIndicator) {
|
|
|
return CustomTabIndicator(
|
|
|
borderSide: BorderSide.lerp(a.borderSide, borderSide, t),
|
|
|
insets: EdgeInsetsGeometry.lerp(a.insets, insets, t)!,
|
|
|
+ width: lerpDouble(a.width, width, t)!,
|
|
|
+ // 渐变插值
|
|
|
+ gradient: Gradient.lerp(a.gradient, gradient, t),
|
|
|
);
|
|
|
}
|
|
|
return super.lerpFrom(a, t);
|
|
|
@@ -46,6 +49,9 @@ class CustomTabIndicator extends Decoration {
|
|
|
return CustomTabIndicator(
|
|
|
borderSide: BorderSide.lerp(borderSide, b.borderSide, t),
|
|
|
insets: EdgeInsetsGeometry.lerp(insets, b.insets, t)!,
|
|
|
+ width: lerpDouble(width, b.width, t)!,
|
|
|
+ // 渐变插值
|
|
|
+ gradient: Gradient.lerp(gradient, b.gradient, t),
|
|
|
);
|
|
|
}
|
|
|
return super.lerpTo(b, t);
|
|
|
@@ -59,21 +65,13 @@ class CustomTabIndicator extends Decoration {
|
|
|
/// 决定控制器宽度的方法
|
|
|
Rect _indicatorRectFor(Rect rect, TextDirection textDirection) {
|
|
|
final Rect indicator = insets.resolve(textDirection).deflateRect(rect);
|
|
|
-
|
|
|
- // 希望的宽度
|
|
|
- double wantWidth = width;
|
|
|
- // 取中间坐标
|
|
|
double cw = (indicator.left + indicator.right) / 2;
|
|
|
|
|
|
- // 下划线靠左
|
|
|
- // return Rect.fromLTWH(indicator.left,
|
|
|
- // indicator.bottom - borderSide.width, wantWidth, borderSide.width);
|
|
|
-
|
|
|
- //下划线居中
|
|
|
+ // 指示器居中
|
|
|
return Rect.fromLTWH(
|
|
|
- cw - wantWidth / 2,
|
|
|
+ cw - width / 2,
|
|
|
indicator.bottom - borderSide.width,
|
|
|
- wantWidth,
|
|
|
+ width,
|
|
|
borderSide.width,
|
|
|
);
|
|
|
}
|
|
|
@@ -90,17 +88,30 @@ class _UnderlinePainter extends BoxPainter {
|
|
|
|
|
|
final CustomTabIndicator decoration;
|
|
|
|
|
|
- /// 决定控制器边角形状的方法
|
|
|
@override
|
|
|
void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
|
|
|
- assert(configuration.size != null);
|
|
|
final Rect rect = offset & configuration.size!;
|
|
|
final TextDirection textDirection = configuration.textDirection!;
|
|
|
final Rect indicator = decoration
|
|
|
._indicatorRectFor(rect, textDirection)
|
|
|
.deflate(decoration.borderSide.width / 2.0);
|
|
|
+
|
|
|
final Paint paint =
|
|
|
- decoration.borderSide.toPaint()..strokeCap = decoration.strokeCap;
|
|
|
+ Paint()
|
|
|
+ ..strokeCap = decoration.strokeCap
|
|
|
+ ..strokeWidth = decoration.borderSide.width;
|
|
|
+
|
|
|
+ // 优先使用渐变色
|
|
|
+ if (decoration.gradient != null) {
|
|
|
+ final gradient = decoration.gradient!;
|
|
|
+ paint.shader = gradient.createShader(
|
|
|
+ Rect.fromPoints(indicator.bottomLeft, indicator.bottomRight),
|
|
|
+ );
|
|
|
+ } else {
|
|
|
+ // 使用纯色
|
|
|
+ paint.color = decoration.borderSide.color;
|
|
|
+ }
|
|
|
+
|
|
|
canvas.drawLine(indicator.bottomLeft, indicator.bottomRight, paint);
|
|
|
}
|
|
|
}
|