|
@@ -0,0 +1,106 @@
|
|
|
|
|
+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),
|
|
|
|
|
+ this.insets = EdgeInsets.zero,
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ /// 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;
|
|
|
|
|
+
|
|
|
|
|
+ /// 新增属性:控制器宽度
|
|
|
|
|
+ final double width;
|
|
|
|
|
+
|
|
|
|
|
+ /// 新增属性:控制器边角形状
|
|
|
|
|
+ final StrokeCap strokeCap;
|
|
|
|
|
+
|
|
|
|
|
+ @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)!,
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+ return super.lerpFrom(a, t);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @override
|
|
|
|
|
+ Decoration? lerpTo(Decoration? b, double t) {
|
|
|
|
|
+ if (b is CustomTabIndicator) {
|
|
|
|
|
+ return CustomTabIndicator(
|
|
|
|
|
+ borderSide: BorderSide.lerp(borderSide, b.borderSide, t),
|
|
|
|
|
+ insets: EdgeInsetsGeometry.lerp(insets, b.insets, t)!,
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+ return super.lerpTo(b, t);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @override
|
|
|
|
|
+ BoxPainter createBoxPainter([VoidCallback? onChanged]) {
|
|
|
|
|
+ return _UnderlinePainter(this, onChanged);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /// 决定控制器宽度的方法
|
|
|
|
|
+ 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,
|
|
|
|
|
+ indicator.bottom - borderSide.width,
|
|
|
|
|
+ wantWidth,
|
|
|
|
|
+ borderSide.width,
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @override
|
|
|
|
|
+ Path getClipPath(Rect rect, TextDirection textDirection) {
|
|
|
|
|
+ return Path()..addRect(_indicatorRectFor(rect, textDirection));
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+class _UnderlinePainter extends BoxPainter {
|
|
|
|
|
+ _UnderlinePainter(this.decoration, VoidCallback? onChanged)
|
|
|
|
|
+ : super(onChanged);
|
|
|
|
|
+
|
|
|
|
|
+ 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;
|
|
|
|
|
+ canvas.drawLine(indicator.bottomLeft, indicator.bottomRight, paint);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|