1. 程式人生 > 其它 >1️⃣通過編寫計算器學習ArkUI元件

1️⃣通過編寫計算器學習ArkUI元件

注:轉自Tuer白曉明,原文地址:https://ost.51cto.com/posts/10480

本系列文章共有五篇,細緻描述瞭如何學習ArkUI元件實現計算器的功能,以下為正文

想要程式做什麼首先自己要明確自己想要什麼,通過分析選題思考程式需要哪些資訊,如何與使用者進行互動,以及以什麼樣的形式反饋給使用者(即UI設計),最終通過執行除錯完成整個應用程式的開發。

1. 做什麼

做一款多功能的計算器,其中型別包含標準計算器、科學計算器、程式設計師計算器、房貸計算器等。

2. 做成什麼樣

計算器給使用者提供多功能選擇,通過按鈕進行互動,文字進行反饋顯示,並通過一系列資料處理,最終反饋給使用者正確的值。可以通過一幅圖或者一個演示Demo來確認是否與預期相符,便於不會因為決策導致返工(本節以標準計算器為例,其他示例不在此處贅述)。

2.1 分析

將整個頁面分為三塊,標題欄,顯示區,功能按鈕區。

  • 標題欄: 通過點選圖示切換不同計算器,同時提供歷史記錄查詢。
  • 顯示區: 通過兩個文字元件分別顯示錄入計算表示式和計算結果。
  • 功能按鈕區: 功能按鈕區分為功能按鈕(如清空,回退等),符號按鈕(如加、減等),及數字按鈕(0-9數字鍵)。

2.2 用到的知識點

對即將實現的標準計算器UI介面分析後,從中提煉出需要用到的技術。

  • 對於實現設計的UI介面,需要了解ArkUI的【佈局約束】;
  • 對於三大塊自上而下的佈局方式,需要了解【Flex佈局】或【Column容器元件】;
  • 對於三大塊內元素(元件)排列,需要了解【Flex佈局】或【Row容器元件】;
  • 對於UI介面中點選選擇,需要了解【Menu控制】;
  • 對於UI介面中單個按鈕元素(元件),需要了解【Button元件】和【點選事件】;
  • 對於UI介面中單個文字顯示元素(元件),需要了解【Text元件】和【@State元件狀態管理】。

3. 編寫程式碼

3.1 分析示例程式碼

建立專案和目錄結構已經在 瞭解一些ArkUI概念並熟悉應用的結構 中介紹過了,有需要可以檢視。開啟index.ets檔案,示例程式碼實現了頁面居中顯示Hello World,先來了解每行程式碼代表的含義。

@Entry
@Component
struct Index {
  build() {...}
}

3.1.1 @Entry
裝飾器

@Entry 註解(裝飾,我更願意稱為註解)的自定義元件(在ArkUI中一切皆為元件,使用已有元件組合構成頁面)作為頁面的預設入口,也可以理解為頁面的根節點。當頁面被載入時,首先建立並呈現@Entry註解的元件,一個頁面中有且僅能使用一個@Entry註解,只有使用@Entry註解的元件或子元件,才會在頁面上顯示。

3.1.2 @Component裝飾器

@Component 註解(裝飾)的程式碼塊具有元件化能力,能夠成為一個獨立的元件,這個型別元件也稱為自定義元件,必須在build()方法描述UI結構,且不能自定義建構函式。

// 這種寫法錯誤,因為缺少build()方法
// 報錯 struct 'MyComponent' must be at least or at most one 'build' method.
@Component
struct MyComponent {
Flex() {}
}

 

自定義元件具有以下特點:

  • 可組合:可以使用內建元件、其他元件、公共屬性和方法組合需要的UI結構,比如使用TextButton元件自定義彈窗元件;
  • 可重用:自定義元件可以被其他元件重用,並作為不同的例項在不同的父元件或容器中使用,比如自定義彈窗可以多次重複使用;
  • 生命週期:生命週期的回撥方法可以在元件中配置,用於業務邏輯處理;
  • 資料驅動更新:由狀態變數的資料驅動,實現UI自動更新。

3.1.3 build()函式(方法)

build() 滿足Build構造器介面定義,用於定義元件的宣告式UI描述。在build方法中以宣告式方式進行組合自定義元件或系統內建元件,在元件建立和更新場景中都會呼叫build方法。build方法僅支援組合元件,使用渲染控制語句。

  build() {
    Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
      Text('Hello World')
        .fontSize(50)
        .fontWeight(FontWeight.Bold)
    }
    .width('100%')
    .height('100%')
  }
 

3.2 Flex容器元件和Flex佈局

通過3.1小節的瞭解,我們可以在被@Entry@Componet註解的程式碼塊中的build函式中使用框架提供的內建基本元件和佈局(容器)元件來構建自定義元件並顯示到頁面中。當然我們也可以不適用容器元件而直接使用基本元件來構建頁面元素,但不推薦這種做法,元件過多無法有效的進行佈局控制。如下程式碼與示例效果相同:

@Entry
@Component
struct Index {
  build() {
    Text('Hello World')
    	.fontSize(50)
    	.fontWeight(FontWeight.Bold)
    	.textAlign(TextAlign.Center)
    	.width('100%')
    	.height('100%')
//    Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
//      Text('Hello World')
//        .fontSize(50)
//        .fontWeight(FontWeight.Bold)
//    }
//    .width('100%')
//    .height('100%')
  }
}
 

為了滿足複雜的、可控的、已維護的UI介面,我們必須對容器元件有一定的瞭解,在不同的場景下使用不同的容器元件,可以快速有效的構建符合需要的UI介面。接下來使用Flex容器元件實現標準計算器三大塊分隔。

3.2.1 Flex容器元件

Flex容器元件稱為彈性佈局元件,通過簡單靈活的控制子元件、並具備響應式,可以實現各種頁面佈局,因此Flex佈局作為首選佈局。

Flex容器元件具有以下特點:

  • 四種子元件佈局模式:Row(行方向)、RowReverse(反Row)、Column(列方向)、ColumnReverse(反列)。
  • 容器元素單行/多行顯示:NoWrap(單行/列布局)、Wrap(多行/列布局)、WrapReverse(反向多行/列布局),均允許元素超出容器。
  • 兩種對齊方式:主軸對齊方式和交叉軸對齊方式。
  • 僅當父元件為Flex容器元件時,還可以設定子元件在主軸方向上基準尺寸(flexBasis)、子元件在容器剩餘空間的比例(flexGrow)、壓縮尺寸分配給子元件(flexShrink)以及設定子元件在容器中交叉軸對齊方式(alignSelf)。
@Entry
@Component
struct Index {
  build() {
    Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center,
      justifyContent: FlexAlign.Center }) {
      Text('主軸與行方向一致作為佈局模式')
        .fontSize(9)
        .fontColor('#CCCCCC')
        .width('90%')
      // 主軸與行方向一致作為佈局模式
      Flex({direction: FlexDirection.Row, wrap: FlexWrap.NoWrap,
        justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center}) {
        Text('A').flexGrow(2).height(100).fontSize(50)
          .backgroundColor('#F2F2F2').textAlign(TextAlign.Center)
        Text('B').flexGrow(1).height(100).fontSize(50)
          .backgroundColor('#E2E2E2').textAlign(TextAlign.Center)
      }
      .width('100%').height(120).padding(10)

      Text('與Row方向相反方向進行佈局')
        .fontSize(9)
        .fontColor('#CCCCCC')
        .width('90%')
      // 與Row方向相反方向進行佈局
      Flex({direction: FlexDirection.RowReverse, wrap: FlexWrap.NoWrap,
        justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center}) {
        Text('A').flexGrow(2).height(100).fontSize(50)
          .backgroundColor('#F2F2F2').textAlign(TextAlign.Center)
        Text('B').flexGrow(1).height(100).fontSize(50)
          .backgroundColor('#E2E2E2').textAlign(TextAlign.Center)
      }
      .width('100%').height(120).padding(10)

      Text('主軸與列方向一致作為佈局模式')
        .fontSize(9)
        .fontColor('#CCCCCC')
        .width('90%')
      // 主軸與列方向一致作為佈局模式
      Flex({direction: FlexDirection.Column, wrap: FlexWrap.NoWrap,
        justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center}) {
        Text('A').flexGrow(2).width('100%').fontSize(50)
          .backgroundColor('#F2F2F2').textAlign(TextAlign.Center)
        Text('B').flexGrow(1).width('100%').fontSize(50)
          .backgroundColor('#E2E2E2').textAlign(TextAlign.Center)
      }
      .width('100%').height(200).padding(10)

      Text('與Column相反方向進行佈局')
        .fontSize(9)
        .fontColor('#CCCCCC')
        .width('90%')
      // 與Column相反方向進行佈局
      Flex({direction: FlexDirection.ColumnReverse, wrap: FlexWrap.NoWrap,
        justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center}) {
        Text('A').flexGrow(2).width('100%').fontSize(50)
          .backgroundColor('#F2F2F2').textAlign(TextAlign.Center)
        Text('B').flexGrow(1).width('100%').fontSize(50)
          .backgroundColor('#E2E2E2').textAlign(TextAlign.Center)
      }
      .width('100%').height(200).padding(10)
    }
    .width('100%')
    .height('100%')
  }
}

3.2.2 標準計算器Flex佈局實現

通過Flex容器佈局構建頁面,子元件以三個Flex容器元件為主,佔比分別為1、2、4,並使用不同的背景色做簡單的區域劃分,程式碼如下:

@Entry
@Component
struct Index {
  build() {
    Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center,
      justifyContent: FlexAlign.Center }) {
      // 頂部功能按鈕
      Flex({direction: FlexDirection.Row}) {}
      .flexGrow(1)
      .width('100%')
      .backgroundColor('#F2F2F2')

      // 回顯及結果顯示區
      Flex({direction: FlexDirection.Column}) {}
      .flexGrow(2)
      .width('100%')
      .backgroundColor('#FFFFFF')

      // 功能按鈕、符號按鈕、數字按鈕
      Flex({direction: FlexDirection.Column}) {}
      .flexGrow(4)
      .width('100%')
      .backgroundColor('#E5E5E5')
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F5F5F5')
  }
}



 

小結

″這並不是完結,而是開始″本篇幅描述了從需求開始一步步到程式碼實現;從設計圖到程式碼實現;從技術要點到程式碼實現。從學到用,從用到學,逐漸掌握ArkUI框架的ets專案開發,下一篇將繼續本篇幅的內容。
由於篇幅有限,僅展示部分知識要點,其他...em...可以嘗試聯絡我