Можно ли наблюдать изменения метрик на компонентах без миксина WidgetsBindingObserver с помощью GlobalKeys? - PullRequest
0 голосов
/ 01 мая 2019

Я пишу оверлейный пакет для флаттера для пошагового руководства.

Чтобы узнать, какие отверстия нужно сделать в оверлее, чтобы сделать виджеты позади него полностью видимыми, функция требует список глобальных ключей, и я использую их для выбора местоположения и размера.

пока наложение все еще видно, виджеты можно анимировать и перемещать в другое место. Есть ли способ обнаружить это, чтобы перерисовать оверлей?

Я знаю, что если я добавлю миксин WidgetsBindingObserver к виджетам, я могу проверить это с помощью didChangeMetrics (). проблема в том, что я не хочу, чтобы пользователь изменял исходный код. Есть ли способ наблюдать метрики виджетов без изменения их кода?

мой код на https://github.com/kfirufk/tuxin_tutorial_overlay

спасибо!

1 Ответ

0 голосов
/ 17 мая 2019

, поэтому благодаря потрясающей поддержке @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;
  }
}
...