初始化
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
//TabBar 自定义指示器:底部一小条,支持纯色/渐变、自定义圆角与离底距离
|
||||
class CustomIndicator extends Decoration {
|
||||
final double width; //指示器宽度
|
||||
final double height; //指示器高度
|
||||
final Color color; //纯色时的颜色
|
||||
final bool isGradient; //是否渐变
|
||||
final List<Color> gradientColors; //渐变色,isGradient 为 true 才生效
|
||||
final double offsetY; //在贴底的基础上再往上移多少
|
||||
final BorderRadius? borderRadius; //圆角,不传默认 1
|
||||
|
||||
const CustomIndicator({
|
||||
this.width = 16.0,
|
||||
this.height = 3.0,
|
||||
this.color = const Color(0xffF68804),
|
||||
this.gradientColors = const [Color(0x00F68804), Color(0xffF68804)],
|
||||
this.isGradient = false,
|
||||
this.offsetY = 0,
|
||||
this.borderRadius,
|
||||
});
|
||||
|
||||
@override
|
||||
BoxPainter createBoxPainter([VoidCallback? onChanged]) => _IndicatorPainter(this, onChanged);
|
||||
|
||||
//必须实现值相等:TabBar 用 indicator != oldWidget.indicator 决定要不要重建 painter
|
||||
//(tabs.dart didUpdateWidget / _IndicatorPainter.shouldRepaint)。调用方都是在 build 里内联
|
||||
//new 出来的,只按引用比较的话每次 rebuild 都判不等 → 白重建画笔、白重绘一次
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
return other is CustomIndicator &&
|
||||
other.width == width &&
|
||||
other.height == height &&
|
||||
other.color == color &&
|
||||
other.isGradient == isGradient &&
|
||||
other.offsetY == offsetY &&
|
||||
other.borderRadius == borderRadius &&
|
||||
listEquals(other.gradientColors, gradientColors);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(width, height, color, isGradient, offsetY, borderRadius, Object.hashAll(gradientColors));
|
||||
}
|
||||
|
||||
class _IndicatorPainter extends BoxPainter {
|
||||
final CustomIndicator deco;
|
||||
|
||||
_IndicatorPainter(this.deco, super.onChanged);
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
|
||||
assert(configuration.size != null);
|
||||
final size = configuration.size!;
|
||||
//横向居中,纵向贴底再上移 offsetY
|
||||
final topLeft = Offset(
|
||||
offset.dx + (size.width - deco.width) / 2,
|
||||
size.height - deco.height - deco.offsetY,
|
||||
);
|
||||
final rect = topLeft & Size(deco.width, deco.height);
|
||||
|
||||
final paint = Paint();
|
||||
if (deco.isGradient) {
|
||||
paint.shader = LinearGradient(colors: deco.gradientColors).createShader(rect);
|
||||
} else {
|
||||
paint.color = deco.color;
|
||||
}
|
||||
|
||||
final borderRadius = deco.borderRadius ?? const BorderRadius.all(Radius.circular(1));
|
||||
canvas.drawRRect(borderRadius.toRRect(rect), paint);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user