在前面的文章中,我们介绍了Dart
的两种编译时,以及Hot reload
模式。今天我们来看下在Flutter
中创建不规则Widget的方式。Android
原生中,我们在创建不规则边界View
时,是通过clipPath
的方式来实现,在Flutter
中也有相关的概念,下面我们来学习下Flutter
中的ClipPath
相关概念及用法。
ClipPath Widget
前面我们说过在Flutter
中Everything is Widget
,那么要使用Path
自然也有对应的Widget
对象-ClipPath
。
ClipPath Extends Map
ClipPath
Widget
继承关系如下图:
enter image description here
ClipPath Introduce
官方文档中ClipPath
说明如下:
A widget that clips its child using a path.
和ClipPath
相关的属性有三个:
- child:
Widget
类型,裁剪的Widget
对象 - clipper:定义裁剪路径的
CustomClipper
对象,其内部提供一个裁剪路径和是否需要重新裁剪 - clipBehavior:裁剪
Widget
的模式,默认取值为Clip.antiAlias
,可选取值有Clip.none
,Clip.hardEdge
,Clip.antiAlias
,Clip.antiAliasWithSaveLayer
.
裁剪模式取值的区别:
- none:无模式
- hardEdge:裁剪速度稍快,但容易失真,有锯齿
- antiAlias:裁剪边缘抗锯齿,使得裁剪更平滑,这种模式裁剪速度比
antiAliasWithSaveLayer
快,但是比hardEdge
慢,该模式常用于圆形和弧形之类的形状裁剪 - antiAliasWithSaveLayer:裁剪后具有抗锯齿特性并分配屏幕缓冲区,所有后续操作在缓冲区进行,然后再进行裁剪和合成
ClipPath Use
在代码中我们可以使用如下代码声明一个ClipPath
Widget
,
1ClipPath(
2 child: Image.asset('images/coffee.jpg'),//裁剪的Widget对象,这里是一个Image Widget
3 clipper: BottomWaveClipper(),//裁剪路径
4 )
复制代码
其中BottomWaveClipper
定义了Image
Widget
的裁剪路径,是CustomClipper
的子类,代码如下:
1class BottomWaveClipper extends CustomClipper<Path>{
2
3 @override
4 Path getClip(Size size) {
5 var path = Path();
6 path.lineTo(0.0, size.height-20);
7
8 //控制点1
9 var firstControlPoint = Offset(size.width/4, size.height);
10 //第一段贝塞尔曲线终点
11 var firstEndPoint = Offset(size.width/2.25, size.height-30);
12 path.quadraticBezierTo(firstControlPoint.dx, firstControlPoint.dy, firstEndPoint.dx, firstEndPoint.dy);
13
14 //控制点2
15 var secondControlPoint = Offset(size.width - (size.width / 3.25), size.height - 65);
16 //第二段贝塞尔曲线终点
17 var secondEndPoint = Offset(size.width, size.height - 40);
18 path.quadraticBezierTo(secondControlPoint.dx, secondControlPoint.dy,
19 secondEndPoint.dx, secondEndPoint.dy);
20
21 path.lineTo(size.width, size.height - 40);
22 path.lineTo(size.width, 0.0);
23 path.close();
24 return path;
25 }
26
27 @override
28 bool shouldReclip(CustomClipper<Path> oldClipper) {
29 //是否重新裁剪
30 return false;
31 }
32}
复制代码
利用上述代码构建的裁剪Image Widget
如下:
enter image description here
完整的WavyHeaderImage Widget
相关代码如下:
1import 'package:flutter/material.dart';
2
3class WavyHeaderImage extends StatelessWidget {
4
5 @override
6 Widget build(BuildContext context) {
7 return ClipPath(
8 child: Image.asset('images/coffee.jpg'),
9 clipper: BottomWaveClipper(),
10 );
11 }
12}
13
14class BottomWaveClipper extends CustomClipper<Path>{
15
16 @override
17 Path getClip(Size size) {
18 var path = Path();
19 path.lineTo(0.0, size.height-20);
20
21 var firstControlPoint = Offset(size.width/4, size.height);
22 var firstEndPoint = Offset(size.width/2.25, size.height-30);
23 path.quadraticBezierTo(firstControlPoint.dx, firstControlPoint.dy, firstEndPoint.dx, firstEndPoint.dy);
24
25 var secondControlPoint = Offset(size.width - (size.width / 3.25), size.height - 65);
26 var secondEndPoint = Offset(size.width, size.height - 40);
27 path.quadraticBezierTo(secondControlPoint.dx, secondControlPoint.dy,
28 secondEndPoint.dx, secondEndPoint.dy);
29
30 path.lineTo(size.width, size.height - 40);
31 path.lineTo(size.width, 0.0);
32 path.close();
33 return path;
34 }
35
36 @override
37 bool shouldReclip(CustomClipper<Path> oldClipper) {
38 return false;
39 }
40}
复制代码
1 @override
2 Widget build(BuildContext context) {
3 return new Scaffold(
4 backgroundColor: Colors.blueGrey,
5 body: WavyHeaderImage(),
6 );
7 }
复制代码
个人微信公众号,欢迎大家加入。
enter image description here