Browse Source

[feat]增加亲密度分析报告页,实现自定义TabBar的渐变色指示器

hezihao 7 tháng trước cách đây
mục cha
commit
8801e3ee0e

+ 16 - 1
lib/module/intimacy_analyse/intimacy_analyse_page.dart

@@ -121,7 +121,22 @@ class IntimacyAnalysePage extends BasePage<IntimacyAnalyseController> {
 
   // 自定义渐变指示器
   CustomTabIndicator _buildGradientLineIndicator() {
-    return CustomTabIndicator(width: 16.0, strokeCap: StrokeCap.round);
+    return CustomTabIndicator(
+      // 指示器的宽度
+      width: 16.0,
+      // 指示器的形状,圆角
+      strokeCap: StrokeCap.round,
+      // 设置渐变色
+      gradient: LinearGradient(
+        colors: [ColorName.colorBrand, ColorName.colorAuxiliary1],
+        begin: Alignment.centerLeft,
+        end: Alignment.centerRight,
+      ),
+      // 指示器距离Tab的外边距
+      insets: EdgeInsets.only(top: 9),
+      // 指示器的高度
+      borderSide: BorderSide(width: 4),
+    );
   }
 
   /// PageView

+ 36 - 25
lib/widget/tabbar/custom_tab_indicator.dart

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