在实际开发中,很多APP里面都会有一些布局需要用到曲线,而不是直线,下面举两个例子,一个是京东APP的页面,一个是淘宝APP的页面,它们都用到了曲线。
在Flutter中可以怎么实现这个效果呢,有一个简单的方法,也有一个复杂的方法。首先简单的方法是什么呢?让UI给一张PNG图片文件,直接贴上去。那复杂的方法又是啥嘞?自定义一个曲线裁剪画布,用来裁剪组件,这篇文章讲的就是这个方法。
下面我们就开始写一个自定义的曲线裁剪组件,新建一个dart文件,并添加下面的代码。
import 'package:flutter/material.dart';
/// 自定义的曲线裁剪组件。
/// 自定义剪辑(`CustomClipper`)抽象类,用于提供自定义剪辑的界面。
class ArcClipper extends CustomClipper<Path> {
// 得到剪辑(`getClip`)抽象方法,给定被剪裁的渲染对象具有给定大小的剪辑描述。
@override
Path getClip(Size size) {
// TODO:自定义的主要操作内容。
}
// 应该重新剪辑(`shouldReclip`)抽象方法,每当为剪辑对象提供自定义剪辑器委托类的新实例时,
// 或者在使用自定义画家委托类的新实例创建新剪辑对象的任何时候调用,这相当于同一事物,因为后者是按前者执行。
@override
bool shouldReclip(CustomClipper<Path> oldClipper) {
// 实现应该重新剪辑(`shouldReclip`)方法。
return true;
}
}
然后我们可以开始画一条线,先感受一下裁剪的效果。
// TODO:自定义的主要操作内容。
// 路径(`Path`)类,平面的复杂一维子集,路径由许多子路径和当前点组成。
// 子路径由各种类型的段组成,例如线、弧或贝塞尔曲线,子路径可以是打开或关闭的,并且可以自相交。
var path = Path();
// 线到(`lineTo`)方法,添加从当前点到给定点的直线段。
// 起点变量。
path.lineTo(0.0, size.height - 39.0);
// 终点变量。
path.lineTo(size.width, 0.0);
path.close();
return path;
下面可以看到红色容器组件被裁剪成了一个倒立的直角三角形。
然后我们再插入一条二次贝塞尔曲线,二次贝塞尔曲线是啥,就是PS里面画一条直线的时候,中间和两边都有可以拖动的小圆点,拖动那3个小圆点可以形成各种曲线,那个就叫二次贝塞尔曲线。
// TODO:自定义的主要操作内容。
// 路径(`Path`)类,平面的复杂一维子集,路径由许多子路径和当前点组成。
// 子路径由各种类型的段组成,例如线、弧或贝塞尔曲线,子路径可以是打开或关闭的,并且可以自相交。
var path = Path();
// 线到(`lineTo`)方法,添加从当前点到给定点的直线段。
// 起点变量。
path.lineTo(0.0, size.height - 39.0);
// 偏移(`Offset`)类,不可变的2D浮点偏移量。
// 第一个控制点和第一点变量。
var firstControlPoint = Offset(size.width / 4, size.height - 73.0);
var firstPoint = Offset(size.width / 2, size.height - 73.0);
// 二次贝塞尔曲(`quadraticBezierTo`)方法,
// 使用控制点(x1,y1)添加从当前点到给定点(x2,y2)的二次贝塞尔曲线段。
// 第一个中间曲线变量。
path.quadraticBezierTo(firstControlPoint.dx, firstControlPoint.dy,
firstPoint.dx, firstPoint.dy);
// 终点变量。
path.lineTo(size.width, 0.0);
path.close();
return path;
下面可以看到,之前的倒立直角三角形已经变成一段二次贝塞尔曲线和直线的组成的一个特殊图形。
最后我们在后半段也添加一个二次贝塞尔曲线,与前半段遥相呼应、左右对称。
// TODO:自定义的主要操作内容。
// 路径(`Path`)类,平面的复杂一维子集,路径由许多子路径和当前点组成。
// 子路径由各种类型的段组成,例如线、弧或贝塞尔曲线,子路径可以是打开或关闭的,并且可以自相交。
var path = Path();
// 线到(`lineTo`)方法,添加从当前点到给定点的直线段。
// 起点变量。
path.lineTo(0.0, size.height - 39.0);
// 偏移(`Offset`)类,不可变的2D浮点偏移量。
// 第一个控制点和第一点变量。
var firstControlPoint = Offset(size.width / 4, size.height - 73.0);
var firstPoint = Offset(size.width / 2, size.height - 73.0);
// 二次贝塞尔曲(`quadraticBezierTo`)方法,
// 使用控制点(x1,y1)添加从当前点到给定点(x2,y2)的二次贝塞尔曲线段。
// 第一个中间曲线变量。
path.quadraticBezierTo(firstControlPoint.dx, firstControlPoint.dy,
firstPoint.dx, firstPoint.dy);
// 第二个控制点和第二点变量。
var secondControlPoint =
Offset(size.width - (size.width / 4), size.height - 73.0);
// 第二个中间曲线变量。
var secondPoint = Offset(size.width, size.height - 39.0);
path.quadraticBezierTo(secondControlPoint.dx, secondControlPoint.dy,
secondPoint.dx, secondPoint.dy);
// 终点变量。
path.lineTo(size.width, 0.0);
path.close();
return path;
然后我们就可以看到一个曲线显现出来了,通过起点变量、第一个控制点与第一点变量(第一个二次贝塞尔曲线)、第二个控制点与第二点变量(第二个二次贝塞尔曲线)和 终点变量,我们成功绘制了一个曲线裁剪。
当我们成功完成了自定义的曲线裁剪组件以后,我们可以通过下面的代码在任意页面使用它。
ClipPath(
clipper: ArcClipper(),
child: Container(
color: Colors.red,
height: 200.0,
),
)