DEV Community

HarmonyOS
HarmonyOS

Posted on

Implementing visibility listening for navigation between the homepage and subpages on the Navigation page.

Read the original article:Implementing visibility listening for navigation between the homepage and subpages on the Navigation page.

Problem Description

The UI page of an application uses the Navigation component as the root view and employs NavPathStack for page transitions. How can we listen to the display and hiding of two pages during the navigation process between the home page and subpages when the onPageShow event is not supported or not executed?

The key code for this issue is as follows:

// Index.ets
@Entry
@Component
struct NavigationPage {
  @Provide('pageInfos') pageInfos: NavPathStack = new NavPathStack();

  // Returning from a subpage to the root page does not trigger.
  onPageShow(): void {
    console.info('NavigationPage onPageShow');
  }

  build() {
    Navigation(this.pageInfos) {
    };
  }
}
// PageOne.ets
@Entry
@Component
export struct PageOne {
  @Consume('pageInfos') pageInfos: NavPathStack;

  // onPageShow will not be triggered
  onPageShow(): void {
    console.info('NavDestination PageOne onPageShow');
  }

  build() {
    NavDestination() {
    };
  }
}
Enter fullscreen mode Exit fullscreen mode

Background Knowledge

onPageShow and onPageHide are triggered only when the router route page is displayed or hidden each time. Other custom component lifecycles cannot trigger these events.

Navigation is the root view container for route navigation, usually serving as the root container for a page (@Entry). NavDestination is the root container for subpages of Navigation.

@ohos.arkui.observer (unaware listening) provides the capability to listen to UI component behavior changes without awareness. You can listen to the page switching event of Navigation using uiObserver.on('navDestinationSwitch').

Solution

The Navigation component is typically used as the root container for a Page. By default, it contains a title bar, a content area, and a toolbar.

In the content area, by default, the home page displays the navigation content (i.e., the child components of Navigation), while subpages display the child components of NavDestination. When navigating from the home page to a subpage, the actual component that is opened is the NavDestination component, not a router page. Therefore, the onPageShow and onPageHide lifecycle methods specific to application pages will not be triggered.

Scenario 1: Listening to the display and hiding of the NavDestination component.

You can use the onShown and onHidden events to listen for the display and hiding of the NavDestination component. For example, refer to the timing sequence of the NavDestination lifecycle.

Scenario 2: Listening to the display and hiding of the Navigation home page.

When the Navigation component does not use hideNavBar to hide the navigation bar, you can listen to the onNavBarStateChange event of Navigation. In the callback function, if the variable isVisible is true, it indicates that the home page is being displayed.

@Entry
@Component
struct NavBarStateChangePage {
  pageInfos: NavPathStack = new NavPathStack();

  @Builder
  pageMap() {
    PageB();
  }

  build() {
    Navigation(this.pageInfos) {
      Column() {
        Button('Navigate to NavDestination page')
          .onClick(() => {
            this.pageInfos.pushPath({ name: 'PageB' });
          });
      };
    }.navDestination(this.pageMap)
    .onNavBarStateChange((isVisible: boolean) => {
      if (isVisible) {
        console.info('Navigation display');
      } else {
        console.info('Navigation Hide');
      }
    });
  }
}

@Component
struct PageB {
  pageInfos: NavPathStack = new NavPathStack();

  build() {
    NavDestination() {
      Button('Return to Navigation')
        .onClick(() => {
          this.pageInfos.pop();
        });
    }.onReady((ctx: NavDestinationContext) => {
      this.pageInfos = ctx.pathStack;
    });
  }
}
Enter fullscreen mode Exit fullscreen mode

Scenario 3: Listening to the display and hiding of the home page and subpages.

Use the imperceptible listener uiObserver.on('navDestinationSwitch') in the aboutToAppear function on the home page to listen for page transitions. The callback function receives NavDestinationSwitchInfo as its parameter, which can be used to determine the pages to hide or display based on the from and to information.

import { uiObserver } from '@kit.ArkUI';

@Entry
@Component
struct NavDestinationSwitchPage {
  pageInfos: NavPathStack = new NavPathStack();

  aboutToAppear(): void {
    // Listen to navigation page switching events
    uiObserver.on('navDestinationSwitch', this.getUIContext(), (switchInfo) => {
      // The visibility of the page can be determined based on the "from" and "to" parameters. If the type is NavDestinationInfo, it indicates a sub-page; if it is NavBar, it indicates a Navigation page.
      console.info(`from ${JSON.stringify(switchInfo.from)} -> to ${JSON.stringify(switchInfo.to)}`);
    });
  }

  aboutToDisappear() {
    uiObserver.off('navDestinationSwitch', this.getUIContext()); // Cancel monitoring
  }

  @Builder
  pageMap() {
    PageA();
  }

  build() {
    Navigation(this.pageInfos) {
      Column() {
        Button('Navigate to NavDestination page')
          .onClick(() => {
            this.pageInfos.pushPath({ name: 'PageA' });
          });
      };
    }.navDestination(this.pageMap);
  }
}

@Component
struct PageA {
  pageInfos: NavPathStack = new NavPathStack();

  build() {
    NavDestination() {
      Button('Return to Navigation')
        .onClick(() => {
          this.pageInfos.pop();
        });
    }.onReady((ctx: NavDestinationContext) => {
      this.pageInfos = ctx.pathStack;
    });
  }
}
Enter fullscreen mode Exit fullscreen mode

Verification Result

Works at API level 18 and later

Written by Simay Ayberik

Top comments (0)