解释
如果你正在读这篇文章,我已经喜欢你了。 这表明您对学习编码的奉献精神。
开始,
#1 按钮
圆形按钮是我们想要的第一件事。
class Btn extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {},
child: Container(
height: 100,
width: 100,
decoration: const BoxDecoration(
color: Colors.blue,
shape: BoxShape.circle,
),
child: const Center(
child: Icon(Icons.arrow_forward_ios, color: Colors.white),
),
),
);
}
}
我们将得到一个简单的按钮,例如:
在代码中,我们想将高度、宽度修改为相同的变量,并且 onTap 也应该从类外部控制,所以我们将代码修改为:
class Btn extends StatelessWidget {
final double size;
final void Function() onTap;
const Btn({
Key? key,
this.size = 100,
required this.onTap,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onTap,
child: Container(
height: size,
width: size,
decoration: const BoxDecoration(
color: Colors.blue,
shape: BoxShape.circle,
),
child: const Center(
child: Icon(Icons.arrow_forward_ios, color: Colors.white),
),
),
);
}
}
#2 电弧指示器
这个会很长
要绘制和控制弧线,我们将使用 Custom Painter。
因此,起始代码将如下所示:
class IndicatorPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
// TODO: implement paint
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
// TODO: implement shouldRepaint
throw UnimplementedError();
}
}
在实现这些功能之前,我们应该有办法在屏幕上看到它。 因此,我们将按钮代码修改为:
class Btn extends StatelessWidget {
final double size;
final void Function() onTap;
const Btn({
Key? key,
this.size = 100,
required this.onTap,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return SizedBox(
height: size + 20,
width: size + 20,
child: Stack(
children: [
SizedBox(
height: size + 20,
width: size + 20,
child: CustomPaint(
painter: IndicatorPainter(),
),
),
Center(
child: GestureDetector(
onTap: onTap,
child: Container(
height: size,
width: size,
decoration: const BoxDecoration(
color: Colors.blue,
shape: BoxShape.circle,
),
child: const Center(
child: Icon(Icons.arrow_forward_ios, color: Colors.white),
),
),
),
),
],
),
);
}
}
现在,我们为弧创建一个 Paint 对象并在 canvas.drawArc() 的帮助下绘制它
class IndicatorPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()
..color = Colors.blue
..strokeWidth = 3
..style = PaintingStyle.stroke;
canvas.drawArc(
const Offset(0, 0) & const Size(120, 120),
0,
10,
false,
paint,
);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return true;
}
}
目前该按钮将如下所示:
现在,我们根据从 0 到 1 的变量值调整弧。
当变量为 0 时,看不到圆弧;当变量为 1 时,圆弧形成一个圆。
class IndicatorPainter extends CustomPainter {
final double value;
IndicatorPainter({
required this.value,
}) : assert(value >= 0 && value <= 1);
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()
..color = Colors.blue
..strokeWidth = 3
..style = PaintingStyle.stroke;
final angle = 6.2832 * value;
canvas.drawArc(
const Offset(0, 0) & const Size(120, 120),
-1.5708,
angle,
false,
paint,
);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return true;
}
}
您可以通过将不同的值(在 1 和 0 之间)传递给 Btn() 中的 IndicatorPainter() 来测试它,例如:
IndicatorPainter(value: 0.1)
或者
IndicatorPainter(value: 0.5)
或者
IndicatorPainter(value: 0.7)
现在,我们只需使用动画控制器控制值。
为此,我们只需通过构造函数将动画控制器的值传递给按钮。
class Btn extends StatelessWidget {
final double size;
final double value;
final void Function() onTap;
const Btn({
Key? key,
this.size = 100,
required this.onTap,
required this.value,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return SizedBox(
height: size + 20,
width: size + 20,
child: Stack(
children: [
SizedBox(
height: size + 20,
width: size + 20,
child: CustomPaint(
painter: IndicatorPainter(value: value),
),
),
Center(
child: GestureDetector(
onTap: onTap,
child: Container(
height: size,
width: size,
decoration: const BoxDecoration(
color: Colors.blue,
shape: BoxShape.circle,
),
child: const Center(
child: Icon(Icons.arrow_forward_ios, color: Colors.white),
),
),
),
),
],
),
);
}
}
现在,在我们使用这个按钮的地方,我们还必须为它定义一个动画控制器。 这可以按如下方式完成:
class _Home extends StatefulWidget {
@override
State<_Home> createState() => __HomeState();
}
class __HomeState extends State<_Home> with TickerProviderStateMixin {
late AnimationController controller;
@override
void initState() {
super.initState();
controller = AnimationController(
vsync: this,
duration: const Duration(seconds: 1),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: AnimatedBuilder(
animation: controller,
builder: (c, child) => Btn(
value: controller.value,
onTap: () {
controller.forward();
},
),
),
),
);
}
}
这篇文章已经太长了。 如果您希望第 2 部分完全了解它是如何工作的,请告诉我。
关注七爪网,获取更多APP/小程序/网站源码资源!
留言与评论(共有 0 条评论) “” |