DEV Community

CoderFeri
CoderFeri

Posted on

Mastering HarmonyOS NEXT Modal Pages: A Comprehensive Guide to Effortless Implementation

Mastering HarmonyOS NEXT Modal Pages: A Comprehensive Guide to Effortless Implementation

0. Preface

Recently, while working on the HarmonyOS NEXT native development of an exam app, I hit a roadblock when it came to displaying the answer sheet for the exam feature. Initially, I used pop - up windows for the answer sheet, but the result was a far cry from expectations—it was so poorly presented that I almost considered resigning out of embarrassment (just kidding). After some reflection, I discovered the "magic weapon" of modal pages, which opened up a whole new world for me. Today, I'd like to share with you how to work with these amazing features.

1. Modal Pages: The "Transformers" of Pop - up Windows 🤖

Imagine you're playing a game, and suddenly a task panel (modal page) pops up. It doesn't block the game screen but allows you to focus on handling the task—that's the charm of modal pages.
It's a "large - panel interactive pop - up window." The biggest difference from regular pop - up windows is that the content is fully customizable, so you can include as much information as you need (such as your exam answer sheet). ArkUI offers two forms:

Semi - modal: A non - full - screen pop - up that allows the underlying page to be partially visible. It's suitable for lightweight operations, like selecting a date or filling in a note.
Full - modal: A domineering full - screen overlay that can only be dismissed by swiping from the side. It's ideal for scenarios that require immersive operations, such as viewing an extra - long answer sheet.

Key point: The semi - modal can be dismissed by swiping, tapping the dimmed background, or clicking the close button. The full - modal, by default, can only be dismissed by swiping, effectively preventing accidental touches by clumsy users!

2. Semi - modal Pages: The Gentle "Side Assistant" 👨💻

Semi - modal pages are like your attentive personal assistants. They don't block the main interface but help you complete tasks quickly. For example, when implementing a "memorial day management" feature, you can select a date and write a note seamlessly.
Lifecycle: The "Heartbeat Record" of the Pop - up 📅
The life cycle of a semi - modal is straightforward:
Before birth (onWillAppear) → Debut (onAppear) → Before disappearance (onWillDisappear) → Exit (onDisappear)
Just like an actor on stage, each stage has its own corresponding "background music" (callback functions), allowing you to "control" its state at any time.
Code Implementation: Step - by - Step Guide to Building a "Memorial Day Assistant" 🚀

@Entry
@Component
struct Index {
  // Define the state of whether the page is displayed (it's just like a switch)
  @State isShow:boolean=false;
  // Selected date: set to today by default to prevent users from choosing magical options like "tomorrow's exam"
  @State selectedDate:Date=new Date();
  // Remark information: left blank for users to fill in
  @State remark:string="";

  // Method to create a semi - modal page: it's like building with blocks, stacking components together
  @Builder
  createSheet() {
    Column({ space: 10 }) { // Column layout, components arranged vertically with a 10px gap
      Row({ space: 10 }) { // Row layout, components arranged horizontally with a 10px gap
        Text("Memorial Day:") // Label to tell users this is for date selection
        // Calendar picker: aligned to the right, with a striking red font color, and allows date selection on click
        CalendarPicker({ hintRadius: 10, selected: this.selectedDate })
          .edgeAlign(CalendarAlign.END)
          .textStyle({ color: "#ff182431", font: { size: 20, weight: FontWeight.Normal } })
          .margin(10)
          .onChange((value) => { // Log the selected date for easy debugging
            console.info("CalendarPicker onChange:" + JSON.stringify(value))
          })
      }
      .margin({ top: 30 }) // 30px top margin to separate from the component above
      .width("90%") // Width takes up 90% of the parent container to avoid overflowing the screen

      Row() { // Remark input box area
        Text("Remark:") // Label
        TextInput({ placeholder: "Please enter remark information" }) // Input box, prompting the user to "write something"
          .onChange(v => { // Update the remark variable in real - time as the user types
            this.remark = v
          })
      }
      .width("90%") // Also takes up 90% width

      // Confirm and save button: shows a Toast when clicked and closes the pop - up
      Button("Confirm and Save")
        .width("80%") // Make the button a bit narrower for a more refined look
        .onClick(() => {
          this.getUIContext().getPromptAction().showToast({
            message: "Memorial Day: " + this.selectedDate.toDateString() + " Remark: " + this.remark
          })
          this.isShow = false; // Close the pop - up, and peace is restored
        })
    }
    .width("90%") // The entire semi - modal content area takes up 90% width
    .padding(20) // 20px internal padding to prevent components from being cramped
  }

  // Main page layout: a button to open the semi - modal
  build() {
    Column({space:20}){
      Text("Semi - modal Page") // Title, simple and straightforward
      Button("Open Semi - modal Page") // Button, clicks to trigger the "switch"
        .bindSheet($$this.isShow,this.createSheet,
          {mode:SheetMode.EMBEDDED, detents: [SheetSize.MEDIUM, SheetSize.LARGE, 300]})
        .onClick(()=>{ // Set the "switch" to on (isShow to true) when clicked
          this.isShow=true;
        })
    }
    .height('100%') // Fill the screen height
    .width('100%') // Fill the screen width
  }
}
Enter fullscreen mode Exit fullscreen mode

Effect Preview: The Transformation from "Ugly Duckling" to "Swan" 📱
Before opening: The main page is clean, with only an "Open" button, like an unopened parcel.
After opening: The semi - modal slides up from the bottom, bringing the calendar and input box, like a "secret drawer" popping out.
During operation: Slide to select the date, enter the remark. The underlying page is dimmed but still visible, constantly reminding you "I'm still here."
When closing: Swipe, tap the dimmed background, or click the button, and the pop - up smoothly disappears, as if nothing happened (but the data has been saved, of course).
Conclusion: Why Are Modal Pages So Great? 🤔
High flexibility: Easily switch between semi - modal and full - modal to adapt to different scenarios (use full - modal for exam answer sheets and semi - modal for date selection).
User - friendly experience: Don't block the main interface, and the operation logic is intuitive (swiping to close is extremely convenient).
Highly customizable: You can write everything from the layout to the interaction, so you can make it as cool as you want (for example, add a sliding page - turning effect to the answer sheet).

Next time, I plan to talk about practical cases of full - modal pages, such as how to use them to create an "immersive exam answer sheet." If you encounter any strange problems during development, feel free to leave a comment, and let's figure them out together! 💪

Where there is a will, there is a way! I'm Feri, an experienced programmer dedicated to the growth of fellow developers. See you next time! 🚗💨

Top comments (0)