前段时间做了一个需求,里面有一个 UI 是实现一个炫酷的 TabBar
切换,但是 Flutter 提供的效果有限。经过自己的摸索最终是实现了,所以个人觉得有必要记录一下。也给需要的看官朋友提供一个思路。
UI 想要的是这样(大致是这个方向,不止这么简单, 还有一些花里胡哨的效果)
但我一把撸的是这样
所以只能模改一番官方的 UnderlineTabIndicator
,详细操作看我怎么抄作业~
抄作业:
1. 找答案
TabBar()
里面有一个属性 indicator
,可以支持自定义指示器
2.抄
- 创建一个文件,命名
rectangle_indicator.dart
(命名随意) - 点进
UnderlineTabIndicator
,全选、Copy - 内容粘贴到
rectangle_indicator.dart
- 然后把相关的类名改成
RectangleIndicator
- 处理一下类名不对应的报错信息
3.改
根据需求修改
indicator(位置、尺寸)
和 paint(样式)
即可
为了更加灵活一点,可以公开一些配置,比如:
// 圆角
final double radius;
// 周围间距
final EdgeInsets padding;
// 颜色
final Color rectangleColor;
// 阴影颜色
final Color? shadowColor;
const RectangleIndicator({
this.borderSide = const BorderSide(width: 2.0, color: Colors.white),
this.insets = EdgeInsets.zero,
this.radius = 4.0,
this.padding = const EdgeInsets.all(2.0),
this.rectangleColor = Colors.redAccent,
this.shadowColor,
}) : assert(borderSide != null),
assert(insets != null);
// 绘制 indicator
void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
assert(configuration != null);
assert(configuration.size != null);
final Rect rect = offset & configuration.size!;
final TextDirection textDirection = configuration.textDirection!;
// 计算 indicator 的 rect
final Rect indicator = decoration._indicatorRectFor(rect, textDirection).deflate(decoration.borderSide.width / 2.0);
// 定义绘制的样式
final RRect rrect = RRect.fromRectAndRadius(indicator, Radius.circular(decoration.radius));
final Paint paint = decoration.borderSide.toPaint()
..style = PaintingStyle.fill
..color = decoration.rectangleColor;
final Path path = Path()..addRRect(rrect.shift(Offset(1, 1)));
// 绘制阴影
if (decoration.shadowColor != null) {
canvas..drawShadow(path, decoration.shadowColor!, 4, false);
}
// 绘制圆角矩形
canvas..drawRRect(rrect, paint);
}
// 计算 indicator 的 rect
Rect _indicatorRectFor(Rect rect, TextDirection textDirection) {
assert(rect != null);
assert(textDirection != null);
final Rect indicator = insets.resolve(textDirection).deflateRect(rect);
return Rect.fromLTWH(
indicator.left + padding.left,
padding.top,
indicator.width - padding.left - padding.right,
indicator.height - padding.top - padding.bottom,
);
}
rectangle_indicator.dart
的修改就到此为止了
使用起来也很简单
**3.交卷 **
本文只是作为日常开发的记录,所以只记录了简单的方向和思路。不同的需求也应又不同的效果,最后还是需要细细雕刻。