要创建一个可以跟随某个 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,以防止内存泄漏。

Flutter 创建跟随 Widget 运动的浮动层

原文地址: https://www.cveoy.top/t/topic/mFf8 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录