Skip to main content

變更 RawMenuAnchor 的關閉順序

關閉 `RawMenuAnchor` 現在會以協調的順序觸發所有 後代 `RawMenuAnchor` 的 `onClose` 與 `onCloseRequested` 回呼(callback)。

摘要

#

關閉 RawMenuAnchor 現在會觸發所有後代 RawMenuAnchoronCloseRequestedonClose 回呼(callback)。 onCloseRequested 回呼會由上而下觸發, 從觸發的 RawMenuAnchor 開始,依序傳遞至其後代, 而 onClose 回呼則由下而上觸發。 若 RawMenuAnchor 已處於關閉狀態, 呼叫 MenuController.closeMenuController.closeChildren 不會觸發 onCloseRequested 回呼。

背景

#

RawMenuAnchor 是一個用於建置自訂選單系統的低階元件 (Widget)。 先前,RawMenuAnchor 在關閉時不會自動通知其後代。 您必須在 onCloseRequested 回呼中手動呼叫 controller.closeChildren(), 才能關閉後代的 RawMenuAnchor

此外,onClose 回呼的觸發時機並不一致。 父級 RawMenuAnchoronClose 可能在其後代完成關閉之前就已執行。

更新後的行為確保當父級 RawMenuAnchor 開始關閉時, 會以由上而下的方式依序觸發所有後代 RawMenuAnchoronCloseRequested

當在 onCloseRequested 中呼叫 hideOverlay 來關閉選單時, 所有後代 RawMenuAnchoronClose 回呼會以由下而上的順序執行。 這表示最近開啟的 RawMenuAnchoronClose 回呼會最先執行, 接著才是其父級,依此類推,直到層級頂端。

此設計允許以協調的關閉順序進行操作, 讓子級 RawMenuAnchor 在其父級完成關閉流程之前, 能夠先執行必要的清理作業。

最後,若 RawMenuAnchor 已處於關閉狀態, 呼叫 MenuController.closeMenuController.closeChildren 不會觸發 onCloseRequested 回呼,以避免不必要的回呼執行。

遷移指南

#

若您的程式碼未覆寫 RawMenuAnchor.onCloseRequested 的預設實作, 或您的 RawMenuAnchor 不包含子選單,則無需進行任何變更。

若您在包含子選單的 RawMenuAnchor 中 自訂了 onCloseRequested 的實作, 則當父選單關閉時,controller.closeChildren() 現在會自動呼叫。 請確認您的 onCloseRequested 實作在這個自動呼叫的情況下仍能正常運作。 在您的 onCloseRequested 回呼中直接呼叫 controller.closeChildren() 已不再必要,請移除這些呼叫。

此外,若您的邏輯依賴父級的 onClose 回呼在後代之前觸發, 請重構您的程式碼以適應新的由下而上的執行順序。

遷移前的程式碼:

dart
RawMenuAnchor(
  controller: menuController,
  onCloseRequested: (hideOverlay) {
    if (!animationController.isForwardOrCompleted) {
      return;
    }

    // Descendant submenus must be closed before the parent menu.
    // This is now handled automatically, so this call is no longer necessary.
    menuController.closeChildren();
    animationController.reverse().whenComplete(hideOverlay);
  },
  onClose: () {
    // This might have executed before descendants called onClose().
    _handleMenuClosed();
  },
  // ...
)

遷移後的程式碼:

dart
RawMenuAnchor(
  controller: menuController,
  onCloseRequested: (hideOverlay) {
    if (!animationController.isForwardOrCompleted) {
      return;
    }

    // `menuController.closeChildren()` is now called automatically.
    animationController.reverse().whenComplete(hideOverlay);
  },
  onClose: () {
    // This now executes only after all descendant submenus have
    // called `onClose()`.
    _handleMenuClosed();
  },
  // ...
)

時間軸

#

導入版本:3.44.0-0.1.pre
穩定版發布:3.44

參考資料

#

API 文件:

相關 issue:

相關 PR: