今天给大家分享Flutter中一个聊天气泡框的做法,简单实用,收藏起来,说不定哪天能用的上
先看效果
高度还原了微信聊天气泡框,支持气泡框自动伸缩,区分发送方和接收方
实现原理
用到了主要是Flutter中的PhysicalShape实现自定义形状图层,通过自定义形状的路径既可实现不同的形状,平时大家用的ClipRRect来实现裁剪圆角矩形也是用的同样的技术。
PhysicalShape
根据官方文档的解释,PhysicalShape可以把child组件进行剪切成path描述的形状,我们这里正好利用这个功能来制作聊天气泡框。
const PhysicalShape({
super.key,
required this.clipper,
this.clipBehavior = Clip.none,
this.elevation = 0.0,
required this.color,
this.shadowColor = const Color(0xFF000000),
super.child,
}) : assert(elevation >= 0.0);
- clipper 执行真正自定义形状的逻辑
- clipBehavior, 如果内容溢出了,要如何裁剪,比如是否要抗锯齿平滑裁剪等等选项
- elevation 控制投影高度
- color 形状填充色
- shadowColor 投影的颜色
重点是CustomClipper
根据官方文档,CustomClipper 是一个抽象类,我们常用的裁剪组件
- ClipRect
- ClipRRect
- ClipOval
- ClipPath
- ShapeBorderClipper
都是继承它来实现的
它重点就2个方法:
- getClip 返回一个path,CustomClipper就是根据这个path来绘制形状图层
- shouldReclip 决定要不要进行重新绘制
开始裁剪
思路: 先画一个矩形,然后在一侧画一个小三角形,这里要注意区分的是发送方、接收方,小三角形的位置是不同的
@override
Path getClip(Size size) {
var path = Path();
if (isMe) {
path.addRRect(
RRect.fromLTRBR(
0,
0,
size.width - nipSize,
size.height,
Radius.circular(radius),
),
);
var path2 = Path();
path2.lineTo(nipSize, nipSize);
path2.lineTo(0, 2 * nipSize);
path2.lineTo(0, 0);
path.addPath(
path2,
Offset(size.width - nipSize, offset + 2 * nipSize),
);
} else {
path.addRRect(
RRect.fromLTRBR(
nipSize,
0,
size.width - nipSize,
size.height,
Radius.circular(radius),
),
);
var path2 = Path();
path2.lineTo(0, 2 * nipSize);
path2.lineTo(-nipSize, nipSize);
path2.lineTo(0, 0);
path.addPath(path2, Offset(nipSize, offset + 2 * nipSize));
}
return path;
}
好了,是不是很简单呢,稍微封装一下,就可以用在自己的项目中了 欢迎关注微信公众号 【技术万有引力】,分享更多实用案例