You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
106 lines
3.6 KiB
106 lines
3.6 KiB
import 'package:flutter/material.dart'; |
|
|
|
class TicketTab extends Decoration { |
|
/// Create an underline style selected tab indicator. |
|
/// |
|
/// The [borderSide] and [insets] arguments must not be null. |
|
const TicketTab({ |
|
this.width = 20, |
|
this.strokeCap = StrokeCap.round, |
|
this.borderSide = const BorderSide(width: 2.0, color: Colors.white), |
|
this.insets = EdgeInsets.zero, |
|
}) : assert(borderSide != null), |
|
assert(insets != null); |
|
|
|
/// 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 TicketTab) { |
|
return TicketTab( |
|
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 TicketTab) { |
|
return TicketTab( |
|
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) { |
|
assert(rect != null); |
|
assert(textDirection != null); |
|
final Rect indicator = insets.resolve(textDirection).deflateRect(rect); |
|
|
|
// 希望的宽度 |
|
double wantWidth = this.width; |
|
// 取中间坐标 |
|
double cw = (indicator.left + indicator.right) / 2; |
|
|
|
print( |
|
'$cw,indicator left${indicator.left}, right ${indicator.right}, indicator top ${indicator.top},indicator bottom${indicator.bottom}, border width${borderSide.width}'); |
|
//这里是核心代码 //下划线靠左 |
|
// 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) |
|
: assert(decoration != null), |
|
super(onChanged); |
|
|
|
final TicketTab decoration; |
|
|
|
///决定控制器边角形状的方法 |
|
@override |
|
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; |
|
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); |
|
} |
|
} |