返回
Flutter BottomAppBar 自定义路径 + 贝塞尔曲线实现闲鱼底部导航
前端
2023-12-01 06:35:27
1. 实现一个自定义的 ShapeBorder
要实现一个自定义的 ShapeBorder,我们需要重写它的 paint
方法。在 paint
方法中,我们可以使用 Path 类来创建想要的形状。
import 'package:flutter/material.dart';
class CustomShapeBorder extends ShapeBorder {
@override
EdgeInsetsGeometry get dimensions => EdgeInsets.all(0.0);
@override
Path getInnerPath(Rect rect, {TextDirection textDirection}) {
return Path()
..lineTo(0.0, rect.height)
..lineTo(rect.width, rect.height)
..lineTo(rect.width, 0.0)
..close();
}
@override
Path getOuterPath(Rect rect, {TextDirection textDirection}) {
return Path()
..lineTo(0.0, rect.height)
..lineTo(rect.width, rect.height)
..lineTo(rect.width, 0.0)
..close();
}
@override
void paint(Canvas canvas, Rect rect, {TextDirection textDirection}) {
Path path = Path()
..moveTo(rect.width / 2 - 20, 0)
..lineTo(rect.width / 2, rect.height)
..lineTo(rect.width / 2 + 20, 0)
..close();
canvas.drawPath(path, Paint()..color = Colors.red);
}
@override
ShapeBorder scale(double t) => this;
}
2. 使用 ShapeBorder 来设置 BottomAppBar 的形状
BottomAppBar(
shape: CustomShapeBorder(),
child: Row(
children: <Widget>[
// ...
],
),
);
3. 使用贝塞尔曲线来创建圆角
Path path = Path()
..moveTo(rect.width / 2 - 20, 0)
..quadraticBezierTo(rect.width / 2, rect.height / 2, rect.width / 2 + 20, 0)
..close();
在上面的代码中,我们使用 quadraticBezierTo
方法来创建了一个贝塞尔曲线。quadraticBezierTo
方法的第一个参数是控制点的坐标,第二个参数是终点的坐标。通过调整控制点的坐标,我们可以控制曲线的形状。
4. 将 ShapeBorder 和 Path 应用到 BottomAppBar
BottomAppBar(
shape: ShapeBorder.lerp(
NotchedShape(),
CustomShapeBorder(),
curve: Curves.easeIn,
textDirection: TextDirection.ltr,
),
child: Row(
children: <Widget>[
// ...
],
),
);
在上面的代码中,我们使用 ShapeBorder.lerp
方法来将 NotchedShape
和 CustomShapeBorder
混合在一起。ShapeBorder.lerp
方法的第一个参数是起始的 ShapeBorder,第二个参数是结束的 ShapeBorder,第三个参数是控制混合程度的曲线,第四个参数是文本方向。通过调整 curve
参数,我们可以控制混合的形状。
5. 完整的代码
import 'package:flutter/material.dart';
class CustomShapeBorder extends ShapeBorder {
@override
EdgeInsetsGeometry get dimensions => EdgeInsets.all(0.0);
@override
Path getInnerPath(Rect rect, {TextDirection textDirection}) {
return Path()
..lineTo(0.0, rect.height)
..lineTo(rect.width, rect.height)
..lineTo(rect.width, 0.0)
..close();
}
@override
Path getOuterPath(Rect rect, {TextDirection textDirection}) {
return Path()
..lineTo(0.0, rect.height)
..lineTo(rect.width, rect.height)
..lineTo(rect.width, 0.0)
..close();
}
@override
void paint(Canvas canvas, Rect rect, {TextDirection textDirection}) {
Path path = Path()
..moveTo(rect.width / 2 - 20, 0)
..lineTo(rect.width / 2, rect.height)
..lineTo(rect.width / 2 + 20, 0)
..close();
canvas.drawPath(path, Paint()..color = Colors.red);
}
@override
ShapeBorder scale(double t) => this;
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
bottomNavigationBar: BottomAppBar(
shape: ShapeBorder.lerp(
NotchedShape(),
CustomShapeBorder(),
curve: Curves.easeIn,
textDirection: TextDirection.ltr,
),
child: Row(
children: <Widget>[
// ...
],
),
),
),
);
}
}