ArkUI in Action: 04-A Complete Atomic Service Case

shaohushuoshaohushuo
3 min read

Share a complete meta-service case, which is a high imitation of Douban's mini program.

Introduction

The entire meta-service is divided into 4-5 pages, the home page is a list page, showing the current popular movies in the theater, and clicking on it is a detailed introduction page, which contains film details, cast lists, related film recommendations, etc., popular posters. Opening the poster is a complete poster display page, click on it to produce a larger picture. Also, there is an introductory page about us.

Design

Instead of using the bottom tab, the meta service places About Us at the bottom of the page and displays it in a more euphemistic way.

Code

  1. Look at the 'entry/src/main/etc/pages/' directory, the whole app is divided into four pages. The route is configured in 'entry/src/main/resources/base/profile/main_pages.json', and the route name corresponds to the file name one-to-one. In the directory where the 'main_pages.json' is located, you can see a 'form_config.json' file, which is used to configure the service card.

Row-column layout is mostly used in the page, and various spacings are preferentially specified by 'Blank()'.

In the Album page, a grid layout is used, when you click on one of the images, a slideshow will be played, here the '@lyb/media-preview' third-party library is used, and the following is the core code:

Grid() {
    ForEach(this.items, (item: Photo, index: number) => {
      GridItem() {
        Image(item.image.normal.url)
          .width('100%')
          .height(140)
          .objectFit(ImageFit.Cover)
          .clickEffect({ level: ClickEffectLevel.MIDDLE, scale: 1.1 })
          .visibility(index == this.index ? Visibility.Hidden : Visibility.Visible)
          .onClick((event) => {
            this.options
              .setInitIndex(index)
              .setMedias(this.getPreviewResources())
              .setIndicator(false)
            MediaPreview.open(this.getUIContext(), this.options)
          })
      }
    })
  }
  .columnsTemplate('1fr 1fr 1fr')
  .columnsGap(2)
  .rowsGap(2)
  .scrollBar(BarState.Off)
  1. The 'common' directory holds some global variables, such as the 'Constants.ets' file, which uses static variables. There is also a simple encapsulation of the request class, which also uses a static class as a singleton.

In order to make the import code more concise, and at the same time "high cohesion and low coupling", an index file is used to export the classes and methods in this directory.

The method in 'Request' uses generics, which automatically deserialize based on the type of passer, reducing the amount of boilerplate code. 3. 'components' component directory. This is where the widgets for each package are stored. In this case, there are 4 widgets: credits, copyright notices, poster lists, and related recommendations.

'Copyright' is a simple widget that appears in the footer.

@Component
export struct Copyright {
  build() {
    Row() {
      Image($r('app.media.nutpi')).width(32)
      Blank().width(8)
      Text('坚果派出品').fontWeight(FontWeight.Bold).fontColor(Color.Gray)
    }.justifyContent(FlexAlign.Center)
    .width('100%')
    .onClick((event) => {
      router.pushUrl({ url: 'pages/About' })
    })
  }
}

4. 'quickactions/pages/QuickActionCard.ets' is the page of the service card, which describes the UI of the card, listening for and triggering click events via Formlink


```plaintext
 FormLink({
      action: this.ACTION_TYPE,
      abilityName: this.ABILITY_NAME,
      params: {
        action: this.MESSAGE
      }
    }) {
      Row() {
        Text('影院热映').fontSize(14)
          .fontColor($r('app.color.card_label'))
        Image($r('app.media.icon'))
          .width(32)
      }
      .justifyContent(FlexAlign.SpaceBetween)
      .height(this.FULL_HEIGHT_PERCENT)
      .width('100%')
      .padding({
        top: 10,
        left: 12,
        right: 12,
        bottom: 10
      })
      .backgroundColor($r('app.color.background_color'))
    }

In the code above, a row layout is described, with icons on the left and app names on the right.

  1. 'viewmodels' is the view data model. There are 5 models in this case, which are 'AppInfo', 'Celebrities', 'Movie', 'Photos', 'Relative'.
export class AppInfo {
  logo: string = '';
  appName: string = '';
  appLinking: string = '';
  appId: string = '';
  desc: string = '';
  type: string = '';
}

'AppInfo' is a simple app information class that contains information such as logo, app name, applink, description, and app type.

Miscellaneous

For more information about app creation, service cards, packaging signatures, and listing reviews, you can check past articles or the reference materials below.

Full code

The full code can be found in the repository https://gitee.com/zacks/arkts-ohos-demo

References

HarmonyOS Native Development Notes Series:

  • [HarmonyOS Native Development Notes: 01-Meta Service Development]

  • [HarmonyOS Native Development Notes: 02-Service Card Development]

  • [HarmonyOS Native Development Notes: 01-Meta Service Development]

  • [HarmonyOS Native Development Notes: 03-Meta Service Development Process]

  • [Harmony Application Packaging and Listing Process](https://gitee.com/zacks/awesome-harmonyos-flutter/blob/master/ Harmony Flutter Practice/Harmony Flutter Practice: 13-Harmony Application Packaging and Listing Process.md)

0
Subscribe to my newsletter

Read articles from shaohushuo directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

shaohushuo
shaohushuo