是否可以使用 GlobalKeys 在没有 WidgetsBindingObserver mixin 的情况下观察组件的指标变化?
is it possible to observe metrics changes on components without WidgetsBindingObserver mixin using GlobalKeys?
我正在为 flutter 写一个覆盖包,用于教程演练。
为了知道在叠加层中打哪些孔以使其后面的小部件完全可见,该函数需要一个全局键列表,我使用它们来获取位置和大小。
虽然叠加层仍然可见,但小部件可以动画化并移动到不同的位置。有没有办法检测到它以便重新绘制叠加层?
我知道如果我将 WidgetsBindingObserver 的混合添加到小部件,我可以使用 didChangeMetrics() 进行检查。问题是我不希望用户修改原始代码。有没有一种方法可以在不更改代码的情况下观察小部件指标?
我的代码在 https://github.com/kfirufk/tuxin_tutorial_overlay
谢谢!
感谢@pskink 的大力支持,我得以妥善解决此问题。
我已经有了要监视大小和位置变化的小部件的全局键,因此我不需要深入了解应用程序中的所有小部件。
所以我添加了一个持久的帧回调,并在其中检查显示的叠加层实际上是否有孔来显示它后面的小部件,如果有,我使用 _sizeVisitor()
函数来检测是否有小部件位置或大小的修改位置,如果它们在哪里,我会重新绘制小部件。
再次......非常感谢@pskink!
void _detectWidgetPositionNSizeChange() {
var bindings = WidgetsFlutterBinding.ensureInitialized();
bindings.addPersistentFrameCallback((d) {
if (visibleOverlayPage != null &&
(visibleOverlayPage.disabledVisibleWidgetsCount +
visibleOverlayPage.enabledVisibleWidgetsCount >
0)) {
for (final widgetGlobalKey in visibleOverlayPage.widgetsGlobalKeys) {
if (_sizeVisitor(widgetGlobalKey)) {
redrawCurrentOverlay();
break;
}
}
}
});
}
bool _sizeVisitor(GlobalKey elementKey) {
if (elementKey.currentContext != null) {
final RenderBox renderBox = elementKey.currentContext.findRenderObject();
bool isChanged = false;
Rect newRect = renderBox.localToGlobal(Offset.zero) & renderBox.size;
_rectMap.update(elementKey, (oldRect) {
if (newRect != oldRect) {
isChanged = true;
}
return newRect;
}, ifAbsent: () => newRect);
return isChanged;
} else {
return false;
}
}
我正在为 flutter 写一个覆盖包,用于教程演练。
为了知道在叠加层中打哪些孔以使其后面的小部件完全可见,该函数需要一个全局键列表,我使用它们来获取位置和大小。
虽然叠加层仍然可见,但小部件可以动画化并移动到不同的位置。有没有办法检测到它以便重新绘制叠加层?
我知道如果我将 WidgetsBindingObserver 的混合添加到小部件,我可以使用 didChangeMetrics() 进行检查。问题是我不希望用户修改原始代码。有没有一种方法可以在不更改代码的情况下观察小部件指标?
我的代码在 https://github.com/kfirufk/tuxin_tutorial_overlay
谢谢!
感谢@pskink 的大力支持,我得以妥善解决此问题。
我已经有了要监视大小和位置变化的小部件的全局键,因此我不需要深入了解应用程序中的所有小部件。
所以我添加了一个持久的帧回调,并在其中检查显示的叠加层实际上是否有孔来显示它后面的小部件,如果有,我使用 _sizeVisitor()
函数来检测是否有小部件位置或大小的修改位置,如果它们在哪里,我会重新绘制小部件。
再次......非常感谢@pskink!
void _detectWidgetPositionNSizeChange() {
var bindings = WidgetsFlutterBinding.ensureInitialized();
bindings.addPersistentFrameCallback((d) {
if (visibleOverlayPage != null &&
(visibleOverlayPage.disabledVisibleWidgetsCount +
visibleOverlayPage.enabledVisibleWidgetsCount >
0)) {
for (final widgetGlobalKey in visibleOverlayPage.widgetsGlobalKeys) {
if (_sizeVisitor(widgetGlobalKey)) {
redrawCurrentOverlay();
break;
}
}
}
});
}
bool _sizeVisitor(GlobalKey elementKey) {
if (elementKey.currentContext != null) {
final RenderBox renderBox = elementKey.currentContext.findRenderObject();
bool isChanged = false;
Rect newRect = renderBox.localToGlobal(Offset.zero) & renderBox.size;
_rectMap.update(elementKey, (oldRect) {
if (newRect != oldRect) {
isChanged = true;
}
return newRect;
}, ifAbsent: () => newRect);
return isChanged;
} else {
return false;
}
}