Browse Source

添加按钮边框动画

weicu
tanlongsheng 1 year ago
parent
commit
559c51378c
  1. 156
      lib/core/widgets/intro_overlay_builder.dart

156
lib/core/widgets/intro_overlay_builder.dart

@ -89,22 +89,9 @@ class IntroOverlayBuilder {
}
static Widget _button(String text, Function() onTap) {
return GestureDetector(
return _AnimatedBorderButton(
text: text,
onTap: onTap,
child: Container(
padding: EdgeInsets.symmetric(horizontal: 10.w, vertical: 5.w),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20.r),
border: Border.all(color: Colors.white),
),
child: Text(
text,
style: TextStyle(
fontSize: 14.sp,
color: Colors.white,
),
),
),
);
}
}
@ -166,3 +153,142 @@ class _AnimatedLottieWidgetState extends State<_AnimatedLottieWidget>
);
}
}
// 新增的带边框流动动画的按钮组件
class _AnimatedBorderButton extends StatefulWidget {
final String text;
final Function() onTap;
const _AnimatedBorderButton({
required this.text,
required this.onTap,
});
@override
_AnimatedBorderButtonState createState() => _AnimatedBorderButtonState();
}
class _AnimatedBorderButtonState extends State<_AnimatedBorderButton>
with SingleTickerProviderStateMixin {
late AnimationController _animationController;
late Animation<double> _animation;
@override
void initState() {
super.initState();
_animationController = AnimationController(
duration: const Duration(seconds: 2),
vsync: this,
);
_animation = Tween<double>(
begin: 0.0,
end: 1.0,
).animate(_animationController);
_animationController.repeat();
}
@override
void dispose() {
_animationController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: widget.onTap,
child: AnimatedBuilder(
animation: _animation,
builder: (context, child) {
return CustomPaint(
painter: _FlowingBorderPainter(
progress: _animation.value,
borderRadius: 20.r,
),
child: Container(
padding: EdgeInsets.symmetric(horizontal: 10.w, vertical: 5.w),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20.r),
border: Border.all(color: Colors.transparent),
),
child: Text(
widget.text,
style: TextStyle(
fontSize: 14.sp,
color: Colors.white,
),
),
),
);
},
),
);
}
}
// 自定义绘制器,用于绘制流动的边框
class _FlowingBorderPainter extends CustomPainter {
final double progress;
final double borderRadius;
_FlowingBorderPainter({
required this.progress,
required this.borderRadius,
});
@override
void paint(Canvas canvas, Size size) {
final rect = Rect.fromLTWH(0, 0, size.width, size.height);
final rrect = RRect.fromRectAndRadius(rect, Radius.circular(borderRadius));
// 计算路径总长度
final path = Path()..addRRect(rrect);
final pathMetrics = path.computeMetrics().first;
final totalLength = pathMetrics.length;
// 流动效果:创建一个渐变的虚线效果
final dashLength = totalLength * 0.3; // 虚线长度
final startOffset = (progress * totalLength) % totalLength;
// 绘制流动的边框段
for (int i = 0; i < 3; i++) {
final offset = (startOffset + i * totalLength / 3) % totalLength;
final endOffset = (offset + dashLength) % totalLength;
Path extractedPath;
if (endOffset > offset) {
extractedPath = pathMetrics.extractPath(offset, endOffset);
} else {
// 处理跨越路径起点的情况
final path1 = pathMetrics.extractPath(offset, totalLength);
final path2 = pathMetrics.extractPath(0, endOffset);
extractedPath = Path()
..addPath(path1, Offset.zero)
..addPath(path2, Offset.zero);
}
// 创建渐变效果
const gradient = LinearGradient(
colors: [
Colors.green,
Colors.yellow,
Colors.red,
],
stops: [0.0, 0.5, 1.0],
);
final gradientPaint = Paint()
..shader = gradient.createShader(rect)
..style = PaintingStyle.stroke
..strokeWidth = 1.5;
canvas.drawPath(extractedPath, gradientPaint);
}
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return true;
}
}

Loading…
Cancel
Save