两种方式在Flutter页面加载完成后,获取指定Widget
的位置和尺寸信息,用来显示弹窗或者新手引导。
方法一: Notification
-
需要自定义的
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); }); } }
-
使用
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
-
定义
GlobalKey
GlobalKey globalKey = GlobalKey();
-
使用
GlobalKey
Container( key: globalKey, ... )
-
获取数据
@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; }); }
-
如果无法直接引用
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
网友评论