| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- import 'dart:ui';
- import 'package:flutter/material.dart';
- /// 自定义Tab的指示器
- class CustomTabIndicator extends Decoration {
- 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,
- });
- final BorderSide borderSide;
- final EdgeInsetsGeometry insets;
- /// 新增属性:控制器宽度
- final double width;
- /// 新增属性:控制器边角形状
- 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);
- }
- @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)!,
- width: lerpDouble(width, b.width, t)!,
- // 渐变插值
- gradient: Gradient.lerp(gradient, b.gradient, 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 cw = (indicator.left + indicator.right) / 2;
- // 指示器居中
- return Rect.fromLTWH(
- cw - width / 2,
- indicator.bottom - borderSide.width,
- width,
- 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) {
- 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 =
- 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);
- }
- }
|