美文网首页
Flutter Code Snippet:获取Widget Of

Flutter Code Snippet:获取Widget Of

作者: 爱抖腿的飞飞 | 来源:发表于2022-02-25 16:49 被阅读0次

    两种方式在Flutter页面加载完成后,获取指定Widget的位置和尺寸信息,用来显示弹窗或者新手引导。

    方法一: Notification

    1. 需要自定义的class

      ///数据封装
      class PositionedNotification extends Notification {
        Offset? offset;
        Size? size;
      }
      
      class PositionedNotificationNotifier extends SingleChildRenderObjectWidget {
        const PositionedNotificationNotifier({Widget? child, Key? key})
            : super(key: key, child: child);
      
        @override
        _PositionedCallback createRenderObject(BuildContext context) {
          ///分发通知
          return _PositionedCallback(onLayoutChangedCallback: (offset, size) {
            (PositionedNotification()
                  ..offset = offset
                  ..size = size)
                .dispatch(context);
          });
        }
      }
      
      class _PositionedCallback extends RenderProxyBox {
        final Function(Offset?, Size?) onLayoutChangedCallback;
        Offset? tmpOffset;
        Size? tempSize;
      
        _PositionedCallback({RenderBox? child, required this.onLayoutChangedCallback})
            : super(child);
      
        @override
        void performLayout() {
          super.performLayout();
          ///widget绘制完成后,分发通知
          SchedulerBinding.instance?.addPostFrameCallback((time) {
            tmpOffset = localToGlobal(Offset.zero);
            tempSize = paintBounds.size;
            onLayoutChangedCallback(tmpOffset, tempSize);
          });
        }
      }
      
    2. 使用

      class App extends StatelessWidget {
        const App({Key? key}) : super(key: key);
      
        @override
        Widget build(BuildContext context) {
          return NotificationListener<PositionedNotification>(
              onNotification: (notification) {
                print("Offset->${notification.offset}");
                print("Size->${notification.size}");
                return true;
              },
              child: const PositionedNotificationNotifier(child: Text("目标Widget")));
        }
      }
      

    方法二: GlobalKey

    1. 定义GlobalKey

      GlobalKey globalKey = GlobalKey();
      
    2. 使用GlobalKey

      Container(
      key: globalKey,
      ...
      )
      
    3. 获取数据

        @override
        void initState() {
              ...
          SchedulerBinding.instance?.addPostFrameCallback((time) {
           BuildContext? context = globalKey.currentContext;
           RenderBox? renderBox = context?.findRenderObject() as RenderBox?;
           Offset? offset = renderBox?.localToGlobal(Offset.zero);
           Size? size = renderBox?.paintBounds.size;
          });
        }
      
    4. 如果无法直接引用GlobalKey,可以使用BuildContext.findAncestorStateOfType()

      class GlobalKeyExampleState extends State<GlobalKeyExample> {
        GlobalKey globalKey = GlobalKey();
      
        static GlobalKeyExampleState? of(BuildContext context) {
          final GlobalKeyExampleState? result =
              context.findAncestorStateOfType<GlobalKeyExampleState>();
          if (result != null) {
            return result;
          }
          return null;
        }
        ...
      }
      
      
      class ChildWidget extends StatefulWidget {
        const ChildWidget({Key? key}) : super(key: key);
      
        @override
        _ChildWidgetState createState() => _ChildWidgetState();
      }
      
      class _ChildWidgetState extends State<ChildWidget> {
        @override
        Widget build(BuildContext context) {
          GlobalKey? globalKey = GlobalKeyExampleState.of(context)?.globalKey;
          return Container(
            key: globalKey,
            ...
          );
        }
      }  
      

    源码

    完整示例代码见GitHub

    相关文章

      网友评论

          本文标题:Flutter Code Snippet:获取Widget Of

          本文链接:https://www.haomeiwen.com/subject/zpaxrrtx.html