Flutter 自定义通知获取Widget的Size

Rasine ·
更新时间:2024-09-20
· 865 次阅读

需求1:在Widget初始化后就发送一次通知
需求2:通知中需要携带Size作为数据

分析:flutter库里有一个SizeChangedLayoutNotification及与其配合工作的SizeChangedLayoutNotifier、_RenderSizeChangedWithCallback ,源码如下。

class SizeChangedLayoutNotification extends LayoutChangedNotification { } class SizeChangedLayoutNotifier extends SingleChildRenderObjectWidget { const SizeChangedLayoutNotifier({ Key key, Widget child, }) : super(key: key, child: child); @override _RenderSizeChangedWithCallback createRenderObject(BuildContext context) { return _RenderSizeChangedWithCallback( onLayoutChangedCallback: () { SizeChangedLayoutNotification().dispatch(context); } ); } } class _RenderSizeChangedWithCallback extends RenderProxyBox { _RenderSizeChangedWithCallback({ RenderBox child, @required this.onLayoutChangedCallback, }) : assert(onLayoutChangedCallback != null), super(child); final VoidCallback onLayoutChangedCallback; Size _oldSize; @override void performLayout() { super.performLayout(); // Don't send the initial notification, or this will be SizeObserver all // over again! if (_oldSize != null && size != _oldSize) onLayoutChangedCallback(); _oldSize = size; } }

但SizeChangedLayoutNotification 在Widget第一次build完成时并不会发送通知,因此需要对_RenderSizeChangedWithCallback的performLayout进行改造。

@override void performLayout() { super.performLayout(); //在第一次layout结束后就会进行通知 if (size != _oldSize) onLayoutChangedCallback(size.height); _oldSize = size; }

同时,为了能将Widget的Size连同通知一起发送出去,需要自定义Notification及Callback。

class NewSizeChangedLayoutNotification extends LayoutChangedNotification{ Size size; NewSizeChangedLayoutNotification(this.size); } class NewSizeChangedLayoutNotifier extends SingleChildRenderObjectWidget { const NewSizeChangedLayoutNotifier({ Key key, Widget child, }) : super(key: key, child: child); @override _NewRenderSizeChangedWithCallback createRenderObject(BuildContext context) { return _NewRenderSizeChangedWithCallback( onLayoutChangedCallback: (Size size) { NewSizeChangedLayoutNotification(size).dispatch(context); } ); } } typedef VoidCallbackWithParam = Function(Size size); class _NewRenderSizeChangedWithCallback extends RenderProxyBox { _NewRenderSizeChangedWithCallback({ RenderBox child, @required this.onLayoutChangedCallback, }) : assert(onLayoutChangedCallback != null), super(child); final VoidCallbackWithParam onLayoutChangedCallback; Size _oldSize; @override void performLayout() { super.performLayout(); //在第一次layout结束后就会进行通知 if (size != _oldSize) onLayoutChangedCallback(size); _oldSize = size; } }

调用:

NotificationListener( onNotification: (notification){ print(notification.size.toString()); return true; }, child: NewSizeChangedLayoutNotifier( child: Container(), ), )

打完,收工。


作者:秋名山交警X



自定义 size flutter

需要 登录 后方可回复, 如果你还没有账号请 注册新账号
相关文章