Mobile Development 19 min read

Building a Simple Notepad App with HarmonyOS Native ArkTS and ArkUI

This tutorial walks you through creating a basic HarmonyOS notepad application using the native ArkTS language and ArkUI components, covering project setup, directory structure, UI layout, routing, and implementing add‑and‑delete functionality with complete code examples.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Building a Simple Notepad App with HarmonyOS Native ArkTS and ArkUI

Introduction

Hello, I am 石小石! In the previous tutorial we used a js‑style web development paradigm to create a simulated dial. In this tutorial we will use the HarmonyOS native ArkTS language to build a simple notepad application, helping you quickly get started with HarmonyOS app development.

Knowledge Review

HarmonyOS SDK

The HarmonyOS SDK is a collection of open capabilities covering six domains such as application framework, services, system, media, AI, and graphics, enabling both "meta‑service development" and "native HarmonyOS app development".

HarmonyOS Native App Development

Native HarmonyOS apps can run on phones, tablets, TVs, car screens, and wearables. To develop native apps you need three basics:

DevEco Studio – the IDE similar to IntelliJ IDEA.

ArkTS – the programming language that extends TypeScript with stricter static checking.

ArkUI – a declarative UI framework built on ArkTS, analogous to the relationship between JavaScript and Element UI.

Building the First Application

Official API documentation can be found at the HarmonyOS developer portal.

Project Creation

Click "Create Project" .

Select "Application" (choose "Atomic Service" for meta‑service development).

Templates indicate which terminals the app can run on.

Project Preview

Click the Previewer button on the right side to view the default project.

Project Directory Structure

├── .hvigor          # temporary build files or config
├── .idea            # IDE configuration
├── AppScope
│   └── entry        # HarmonyOS module, compiled into a HAP package
│       ├── src
│       │   ├── main
│       │   │   └── ets
│       │   │       ├── entryability        # app/service entry
│       │   │       │   └── [ArkTS source files]
│       │   │       └── entrybackupability # backup/restore capability
│       │   │           └── [ArkTS source files]
│       │   ├── pages                     # pages of the app/service
│       │   │   └── Index.ets             # page source file
│       │   └── resources                 # resource files
│       │       └── mock
│       │           └── ohosTest
│       │               ├── test
│       │               │   └── .gitignore
│       │               ├── build-profile.json5
│       │               ├── hvigorfile.ts
│       │               ├── obfuscation-rules.txt
│       │               └── oh-package.json5
│       └── module.json5                # module config
├── .gitignore
├── build-profile.json5
├── hvigorfile.ts
├── obfuscation-rules.txt
├── oh-package.json5
└── oh_modules
    ├── .gitignore
    ├── build-profile.json5
    ├── hvigorfile.ts
    ├── local.properties
    └── oh-package-lock.json5

For beginners the structure can be simplified to focus on the pages folder and module.json5 for page configuration.

Code Overview

The default template contains minimal code. Below is the basic entry component:

@Entry
@Component
struct Index {
  @State message: string = 'Hello World';

  build() {
    RelativeContainer() {
      Text(this.message)
        .id('HelloWorld')
        .fontSize(50)
        .fontWeight(FontWeight.Bold)
        .alignRules({
          center: { anchor: '__container__', align: VerticalAlign.Center },
          middle: { anchor: '__container__', align: HorizontalAlign.Center }
        })
    }
    .height('100%')
    .width('100%')
  }
}

Key concepts include decorators (@Entry, @Component, @State), declarative UI description, custom components, system components, and chainable property methods.

Building the First Page

Page Description

The page contains a centered button that navigates to a second page.

@Entry
@Component
struct Index {
  build() {
    Row() {
      // Add button component
      Button() {
        Text('你好,鸿蒙')
          .fontSize(22)
          .fontColor('#fff')
          .fontWeight(FontWeight.Bold)
      }
      .type(ButtonType.Normal)
      .borderRadius('10%')
      .margin({ top: 20 })
      .backgroundColor('#ff9c6e')
      .width('40%')
      .height('5%')
      .onClick(() => {
        router.pushUrl({ url: 'pages/Second' })
      })
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#d4380d')
    .alignItems(VerticalAlign.Center)
    .justifyContent(FlexAlign.Center)
  }
}

Page Layout

Using Row to center the button and applying width, height, backgroundColor, alignItems, and justifyContent properties.

Navigation

Import the router module and call router.pushUrl({url: 'pages/Second'}) inside the button's onClick handler.

Building the Second Page

Create Second Page

Right‑click the pages folder, choose New > ArkTS File , name it Second , and add the following content:

@Entry
@Component
struct Second {
  @State message: string = '这是第二个页面'

  build() {
    Row() {
      Column() {
        Text(this.message)
      }
      .width('100%')
    }
    .height('100%')
  }
}

Configure Route

Add "pages/Second" to the src array in main_pages.json under the base/profile directory.

{
  "src": [
    "pages/Index",
    "pages/Second"
  ]
}

Notepad Page Implementation

Page Description

The page should contain a text input, an "Add" button, and a list displaying the notes.

Basic Layout

@Entry
@Component
struct NotesPage {
  @State notes: string[] = ['事项1', '事项2', '事项3'];
  @State newNote: string = '';

  build() {
    Column() {
      Text('石小石的记事本')
        .fontSize(24)
        .fontColor('#003eb3')
        .margin({ top: 20, bottom: 20 });

      TextInput({
        text: this.newNote,
        placeholder: '添加新的事项'
      })
      .width('80%')
      .margin({ bottom: 10 })
      .padding(10)
      .fontSize(16)
      .borderColor('#ccc')
      .borderWidth(1)
      .borderRadius(5)
      .onChange((value:string) => { this.newNote = value });

      Button('添加')
        .onClick(() => this.addNote())
        .width('80%')
        .padding(10)
        .fontSize(16)
        .backgroundColor('#007AFF')
        .fontColor('#FFF')
        .borderRadius(5);

      List() {
        ForEach(this.notes, (item:string, index:number) => {
          ListItem() {
            Row() {
              Text(item).fontColor('#001d66');
              Button('删除')
                .onClick(() => this.deleteNote(index))
                .fontSize(14)
                .height(18)
                .backgroundColor('#ff4d4f')
                .type(ButtonType.Normal)
                .borderRadius('15%')
                .padding({ left:10, right:10 });
            }
            .width('100%')
            .justifyContent(FlexAlign.SpaceBetween)
            .backgroundColor('#bae0ff')
            .margin({ bottom:5 })
            .padding(5);
          }
        })
      }
      .width('80%')
      .margin({ top:20 });
    }
    .width('100%')
    .backgroundColor('#e6f4ff')
    .height('100%');
  }

  addNote() {
    if (this.newNote.trim() !== '') {
      this.notes.push(this.newNote);
      this.newNote = '';
    }
  }

  deleteNote(index: number) {
    this.notes.splice(index, 1);
  }
}

Full Code and Demo

Below are the complete source files for the initial page and the notepad page, demonstrating navigation, UI layout, and add/delete functionality.

// Index.ets (initial page)
import { router } from '@kit.ArkUI';

@Entry
@Component
struct Index {
  @State message: string = 'Hello World';

  build() {
    Row() {
      Button() {
        Text('你好,鸿蒙')
          .fontSize(22)
          .fontColor('#fff')
          .fontWeight(FontWeight.Bold)
      }
      .type(ButtonType.Normal)
      .borderRadius('10%')
      .margin({ top: 20 })
      .backgroundColor('#ff9c6e')
      .width('40%')
      .height('5%')
      .onClick(() => {
        router.pushUrl({ url: 'pages/Second' })
      })
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#d4380d')
    .alignItems(VerticalAlign.Center)
    .justifyContent(FlexAlign.Center)
  }
}
// NotesPage.ets (notepad page)
@Entry
@Component
struct NotesPage {
  @State notes: string[] = ['事项1', '事项2', '事项3'];
  @State newNote: string = '';

  addNote() {
    if (this.newNote.trim() !== '') {
      this.notes.push(this.newNote);
      this.newNote = '';
    }
  }

  deleteNote(index: number) {
    this.notes.splice(index, 1);
  }

  build() {
    Column() {
      Text('石小石的记事本')
        .fontSize(24)
        .fontColor('#003eb3')
        .margin({ top: 20, bottom: 20 });

      TextInput({ text: this.newNote, placeholder: '添加新的事项' })
        .onChange((value:string) => { this.newNote = value })
        .width('80%')
        .margin({ bottom: 10 })
        .padding(10)
        .fontSize(16)
        .borderColor('#ccc')
        .borderWidth(1)
        .borderRadius(5);

      Button('添加')
        .onClick(() => this.addNote())
        .width('80%')
        .padding(10)
        .fontSize(16)
        .backgroundColor('#007AFF')
        .fontColor('#FFF')
        .borderRadius(5);

      List() {
        ForEach(this.notes, (item:string, index:number) => {
          ListItem() {
            Row() {
              Text(item).fontColor('#001d66');
              Button('删除')
                .onClick(() => this.deleteNote(index))
                .fontSize(14)
                .height(18)
                .backgroundColor('#ff4d4f')
                .type(ButtonType.Normal)
                .borderRadius('15%')
                .padding({ left:10, right:10 });
            }
            .width('100%')
            .justifyContent(FlexAlign.SpaceBetween)
            .backgroundColor('#bae0ff')
            .margin({ bottom:5 })
            .padding(5);
          }
        })
      }
      .width('80%')
      .margin({ top:20 });
    }
    .width('100%')
    .backgroundColor('#e6f4ff')
    .height('100%');
  }
}

Conclusion

This tutorial demonstrates how to use native ArkTS together with ArkUI components to create a simple welcome page and a functional notepad page on HarmonyOS. It covers code structure, UI component usage, routing configuration, and basic add/delete event handling, providing a solid foundation for further HarmonyOS development.

mobile developmentHarmonyOSTutorialArkUIArkTSNotepad App
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.