Flutter 创建跟随 Widget 运动的浮动层
要创建一个可以跟随某个 Widget 运动的浮动层,可以使用 Overlay 和 OverlayEntry 类。
首先,需要在页面的 build 方法中创建一个 Overlay widget,这将用来组合所有的 OverlayEntry。然后,在需要添加浮动层的位置,可以使用 Overlay.of(context) 获取到 Overlay widget,然后创建一个 OverlayEntry 并添加到 Overlay widget 中。
下面是一个示例代码:
import 'package:flutter/material.dart';
class FollowWidget extends StatefulWidget {
final Widget child;
const FollowWidget({Key? key, required this.child}) : super(key: key);
@override
_FollowWidgetState createState() => _FollowWidgetState();
}
class _FollowWidgetState extends State<FollowWidget> {
late OverlayEntry overlayEntry;
GlobalKey followKey = GlobalKey();
@override
void initState() {
super.initState();
overlayEntry = OverlayEntry(
builder: (BuildContext context) {
final RenderBox? followBox = followKey.currentContext?.findRenderObject() as RenderBox?; // 获取目标 Widget 的 RenderBox
if (followBox == null) {
return Container();
}
final Offset followOffset = followBox.localToGlobal(Offset.zero); // 获取目标 Widget 的位置
return Positioned(
top: followOffset.dy + followBox.size.height, // 设置浮动层的位置
left: followOffset.dx,
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.2),
blurRadius: 5,
spreadRadius: 2,
offset: Offset(0, 2),
),
],
),
padding: EdgeInsets.all(16),
child: Text('This is a floating widget'),
),
);
},
);
}
@override
void dispose() {
overlayEntry.remove();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Stack(
children: [
widget.child, // 主 Widget
Positioned(
key: followKey, // 为目标 Widget 设置 GlobalKey
top: 100,
left: 100,
child: GestureDetector(
onTap: () {
if (overlayEntry.mounted) {
overlayEntry.remove(); // 移除浮动层
} else {
Overlay.of(context)?.insert(overlayEntry); // 添加浮动层
}
},
child: Container(
width: 100,
height: 50,
color: Colors.blue,
child: Center(
child: Text('Follow me'),
),
),
),
),
],
);
}
}
在这个示例中,我们首先在 build 方法中创建了一个 Stack,将 child widget 和浮动层添加到同一个 Stack 中。然后,在浮动层的位置使用了一个 GestureDetector,当用户点击时,会根据 OverlayEntry 是否已经添加来添加或移除浮动层。
OverlayEntry 的 builder 方法中,我们首先获取了需要跟随的 widget 的 RenderBox,然后根据其位置计算浮动层的位置,并返回一个 Positioned widget。在 Positioned widget 中,我们包裹了一个 Container,用来显示浮动层的内容。
最后,需要在 State 的 dispose 方法中移除 OverlayEntry,以防止内存泄漏。
原文地址: https://www.cveoy.top/t/topic/mFf8 著作权归作者所有。请勿转载和采集!