边框中的颤动箭头
Flutter arrow in border
我想添加一个轻量级的导航栏来切换登录和注册。
结果应如下所示:
箭头应指示当前所选页面。
参考这个,问题中的UI与你的相似,答案中使用的概念可以根据你的需要进行调整。
这对我有用:
class TapBarDesign extends StatefulWidget {
const TapBarDesign({Key? key}) : super(key: key);
@override
_TapBarDesignState createState() => _TapBarDesignState();
}
class _TapBarDesignState extends State<TapBarDesign>
with SingleTickerProviderStateMixin {
@override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
backgroundColor: Colors.blue,
appBar: AppBar(
toolbarHeight: 0,
backgroundColor: Colors.transparent,
elevation: 0,
bottom: TabBar(
indicatorSize: TabBarIndicatorSize.tab,
indicator: ArrowTabBarIndicator(),
tabs: const <Widget>[
Tab(
child: Text(
'Page 1',
),
),
Tab(
child: Text(
'Page 2',
),
),
],
),
),
body: const TabBarView(
children: <Widget>[
Center(child: Text('Page 1')),
Center(child: Text('Page 2')),
],
),
),
);
}
}
class ArrowTabBarIndicator extends Decoration {
final BoxPainter _painter;
ArrowTabBarIndicator({double width = 20, double height = 10})
: _painter = _ArrowPainter(width, height);
@override
BoxPainter createBoxPainter([VoidCallback? onChanged]) => _painter;
}
class _ArrowPainter extends BoxPainter {
final Paint _paint;
final double width;
final double height;
_ArrowPainter(this.width, this.height)
: _paint = Paint()
..color = Colors.white
..strokeWidth = 1
..strokeCap = StrokeCap.round;
@override
void paint(Canvas canvas, Offset offset, ImageConfiguration cfg) {
const pointMode = ui.PointMode.polygon;
if (cfg.size != null) {
final points = [
Offset(0, cfg.size!.height),
Offset(cfg.size!.width / 2 - (width / 2), cfg.size!.height) + offset,
Offset(cfg.size!.width / 2, (cfg.size!.height + height)) + offset,
Offset(cfg.size!.width / 2 + (width / 2), cfg.size!.height) + offset,
Offset(cfg.size!.width * 2, cfg.size!.height),
];
canvas.drawPoints(pointMode, points, _paint);
}
}
}
我想添加一个轻量级的导航栏来切换登录和注册。 结果应如下所示:
箭头应指示当前所选页面。
参考这个
这对我有用:
class TapBarDesign extends StatefulWidget {
const TapBarDesign({Key? key}) : super(key: key);
@override
_TapBarDesignState createState() => _TapBarDesignState();
}
class _TapBarDesignState extends State<TapBarDesign>
with SingleTickerProviderStateMixin {
@override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
backgroundColor: Colors.blue,
appBar: AppBar(
toolbarHeight: 0,
backgroundColor: Colors.transparent,
elevation: 0,
bottom: TabBar(
indicatorSize: TabBarIndicatorSize.tab,
indicator: ArrowTabBarIndicator(),
tabs: const <Widget>[
Tab(
child: Text(
'Page 1',
),
),
Tab(
child: Text(
'Page 2',
),
),
],
),
),
body: const TabBarView(
children: <Widget>[
Center(child: Text('Page 1')),
Center(child: Text('Page 2')),
],
),
),
);
}
}
class ArrowTabBarIndicator extends Decoration {
final BoxPainter _painter;
ArrowTabBarIndicator({double width = 20, double height = 10})
: _painter = _ArrowPainter(width, height);
@override
BoxPainter createBoxPainter([VoidCallback? onChanged]) => _painter;
}
class _ArrowPainter extends BoxPainter {
final Paint _paint;
final double width;
final double height;
_ArrowPainter(this.width, this.height)
: _paint = Paint()
..color = Colors.white
..strokeWidth = 1
..strokeCap = StrokeCap.round;
@override
void paint(Canvas canvas, Offset offset, ImageConfiguration cfg) {
const pointMode = ui.PointMode.polygon;
if (cfg.size != null) {
final points = [
Offset(0, cfg.size!.height),
Offset(cfg.size!.width / 2 - (width / 2), cfg.size!.height) + offset,
Offset(cfg.size!.width / 2, (cfg.size!.height + height)) + offset,
Offset(cfg.size!.width / 2 + (width / 2), cfg.size!.height) + offset,
Offset(cfg.size!.width * 2, cfg.size!.height),
];
canvas.drawPoints(pointMode, points, _paint);
}
}
}