整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          鴻蒙App開發實戰

          鴻蒙App開發實戰

          、概述

          在2021年6月2日,華為發布了鴻蒙系統--HarmonyOS它是一款“面向未來”、面向全場景(移動辦公、運動健康、社交通信、媒體娛樂等)的分布式操作系統。

          在傳統的單設備系統能力的基礎上,HarmonyOS提出了基于同一套系統能力、適配多種終端形態的分布式理念,能夠支持手機、平板、智能穿戴、智慧屏、車機等多種終端設備。

          簡而言之:HarmonyOS是一款面向物聯網的系統。搞過智能家居的朋友應該知道,聯網真是一個大問題,具體細節,我就不多說了,誰用誰知道。如果現在用安裝了HarmonyOS的路由器,用安裝HarmonyOS的手機和智慧屏,那分布式的意義就被激出來了,yyds。

          如果你是硬件工程師和單片機程序員,你可以實現將操作系統安裝在硬件設備上,然后實現設備操作,還有跟App的交互;對于應用工程師而言,你可以開發App并安裝在手機、平板或手表上。我怕弄硬件設備時,會被電到,所以選擇開發App的方向。

          如果你錯過了iOS App的淘金時代,錯過Android App的外包時機,想在鴻蒙App中,能賺到買一份盒飯的錢,那你就該馬上關注我,好恰飯。

          那什么人學鴻蒙App開發有優勢?--懂Java的人和懂前端的人,還有我這種既懂Java又懂前端的人,哈哈...,不要打我,要關注我。

          HarmonyOS支持的開發語言包括Java、XML、C/C++ 、 JS、CSS和HML(HarmonyOS Markup Language),其中UI ,用Java和JS實現。

          好了,今天就說這么多,下節就正式進入App開發階段。

          二、創建項目

          學一門編程語言,廢話再多,都不如動手實踐來得簡單。走,去
          https://developer.harmonyos.com/cn/develop/deveco-studio#download下載屬于你操作系統的開發工具。工具安裝太簡單了,簡單到我都不想說了。

          打開HUAWEI DevEco Studio開發工具,用過jetbrains全家桶中(Java、Python、PHP或C#等)開發工具中一個或多個的程序員,都會倍感親切,因為它是基于IntelliJ IDEA Community的開源版本打造而來的。

          好了,好了,知道你等不急,準備大干一場了。那就話不多說,直接進入主題吧。

          1. 創建項目

          DevEco Studio升級之后,創建項目的窗口如下,單擊【Create HarmonyOS Project】,進入下一個窗口。

          選擇第2個:Empty Ability(Java),接著用你的神力按下右下角的【Next】按鈕。

          項目配置信息窗口,要填寫的內容如下:

          Project Name:項目名稱,暫叫Booking,假裝你是一個很愛讀書的家伙;

          Project Type: 項目類型,Service--免安裝的原子化服務,Application--應用程序,選后面這個。

          Package Name:包名。一般就是網址的域名+項目名稱,這個用于區分不同的App,我隨便寫了一個,你也可以隨便寫一個;

          Sava Location:項目保存目錄,我用的是一臺用好幾個臉盆換來的蘋果電腦,所以你看不到C:這樣的,你用Windows的話,選擇放在D:盤的某個文件夾下就好了,開發步驟和工具都是一個樣的,只是這種目錄略有不同而已;

          Compaible API Version:編譯API的版本,選擇SDK:API Version 5;

          Device Type:程序支持的設備,不要貪多,選擇支持手機Phone先,等以后有機會了,再擴展到平板:Tablet,智慧屏(如門禁人臉識別屏):TV,穿戴設備(如手表):Wearable和汽車:Car;

          Show in Service Center:是否在服務中心露出。如果Project Type為Service,則會同步創建一個2*2的服務卡片模板,同時還會創建入口卡片;如果Project Type為Application,則只會創建一個2*2的服務卡片模板。

          按下【Finish】按鈕之后,一個叫Booking的鴻蒙App項目就創建好了。

          2. 安裝HarmonyOS SDK

          找到【Tools】菜單欄并點擊它,選擇【SDK Manager】,在彈出的窗口中,選擇你想安裝的SDK版本。找到HarmonyOS SDK,勾選第1或第2項,我勾選了SDK(API Version5),點擊【Apply】之后,就會開始下載并安裝自動安裝的。如果已經安裝的,跳過這一步。

          安裝不會太久,稍等一下就好了。如果著急的話,我告訴你一個方法,那就是在心中默念:馬上就好了,馬上就好了。

          3. 安裝模擬器

          若想運行鴻蒙App,一是用安裝了HarmonyOS系統的手機運行,二是用模擬器運行。考慮到好多朋友還沒賺到買HarmonyOS手機的錢,所有選擇用第2種方式。

          找到【Tools】菜單欄并點擊它,選擇【Device Manager】,在彈出的窗口中,要求你進行登錄Login,這是因為模擬器目前只能支持遠程調試(本地的還在開發當中),你登錄就是了。如果沒有登錄賬號,自己去
          https://developer.harmonyos.com/cn/ 注冊一下就好了。

          Remote Emulator每次使用時長為1小時,到期后會自動釋放資源,當然,你可以重新申請。這就是要登錄的原因了。希望快點發布可以下載到本地的模擬器Local Emulator。

          成功登錄之后,會顯示出可用的虛擬機,列表如下。單擊手機P40所在行的運行圖標(最后面那個箭頭圖標),就會啟動手機的虛擬機。

          4. 運行App

          在開發工具的主窗口中,你可以看到鴻蒙手機P40的虛擬機。眼光往虛擬機上方瞟一瞟,有沒有見到:【entry】【HUAWEI ANA-AN00】后的的箭頭沒?--單擊它,運行鴻蒙App。運行可能會有點慢,需要稍等片刻。

          右下角有:【Deploying HAP......】告訴你在努力發布中。

          等了7749秒,終于運行成功了,效果如下:

          你好,世界

          三、項目文件詳解

          在進行鴻蒙App功能開發之前,你應該對HarmonyOS App的邏輯結構,有所了解。鴻蒙App要發布的程序,需要打包成HAP(HarmonyOS Ability Package)格式。一個App由代碼、資源、第三方庫及應用清單文件組成,項目結構如下圖2.1所示。

          圖 2.1 項目結構

          gradle:Gradle配置文件,由開發工具自動生成,一般情況下不需要進行修改;

          entry:默認啟動模塊(主模塊),程序員用于編寫源碼文件以及開發資源文件的目錄:

          entry>libs:用于存放entry模塊的依賴文件,如Java庫文件(.jar);

          entry>src>main>Java:用于存放Java源碼,這是程序員開發功能的地方;

          entry>src>main>resources:用于存放應用所用到的資源文件,如圖形、多媒體、字符串、布局文件等,這是程序員配置資源的地方,它包括兩大類目錄,一類為base目錄與限定詞目錄,另一類為rawfile目錄。

          base 目錄中的資源文件會被編譯成二進制文件,并賦予資源文件ID,如存放字符串的文件string.json;rawfile目錄中的資源文件會被直接打包進應用,不經過編譯,也不會被賦予資源文件ID,如js文件。

          base下資源組目錄element、media、animation、layout、graphic和profile的作用,如圖2.2所示:

          圖2.2 資源文件解析

          entry>src>main>config.json:HAP清單文件;

          entry>src>test:編寫代碼單元測試代碼的目錄,運行在本地Java虛擬機上;

          entry>.gitignore:標識git版本管理需要忽略的文件;

          entry>build.gradle:entry模塊的編譯配置文件。

          項目文件內容的解析就這么多,你不用背記下來,大概知道每個目錄和文件的作用是什么就好了。這些文件會在開發的過程中,慢慢熟悉的,不用著急。

          其實,鴻蒙App的整體內容,并沒有那么復雜,開發應用代碼主要圍繞Ability組件展開。你在項目中,看到MainAbility,就是Ability來的。

          為了方便開發和維護,將頁面Ability的資源放到resources中,再用自動生成的代碼進行引用,是一個不錯的分層解決方案,這也是存在resources原因,明白了么?

          四、Ability介紹

          Ability是鴻蒙App的重要組成部分,分為Page Ability、Service Ability和Data Ability三類,它們的區別如下:

          Page Ability:構造和用戶交互的窗口,像你用App,在看我這篇文章的當前屏幕,就是一個窗口,在窗口中,你可以做一些交互動作,如轉發、點贊或留言。如圖3.1,顯示"你好,世界"的也是一個窗口。

          圖3.1 App窗口

          Service Ability:用于提供后臺運行任務的能力,就像你打開音樂App,選一首歌播放之后,繼續選其他歌曲,此時播放的歌曲就是運行在后臺,用Service實現的功能;

          Data Ability:用于對外部提供統一的數據訪問抽象,就是那種專門操作數據用的接口。

          為了更好理解,特將Page Ability叫成Feature(要臉的) Ability,簡稱FA;而將Service Ability和Data Ability歸類成Particle(不要臉的) Ability,簡稱PA。

          肉眼,一望,就可以看得出誰要臉誰不要臉;鴻蒙App,在config.json中一配,就可以看得出Ability是要臉的還是不要臉的。

          在配置文件(config.json)中注冊Ability時,可以通過配置Ability元素中的“type”屬性來指定Ability模板類型。其中,“type”的取值可以為“page”、“service”或“data”,分別代表Page模板、Service模板和Data模板。

          "abilities": [
            {
              "skills": [
                {
                  "entities": [
                    "entity.system.home"
                  ],
                  "actions": [
                    "action.system.home"
                  ]
                }
              ],
              "orientation": "unspecified",
              "name": "com.lc.hm.booking.MainAbility",
              "icon": "$media:icon",
              "description": "$string:mainability_description",
              "label": "$string:entry_MainAbility",
              "type": "page",
              "launchType": "standard"
            }
          ]

          五、Ability和AbilitySlice區別

          在Booking項目中,有一個MainAbility.java文件,它就是要臉的Ability。一個要臉的Ability由多個業務能力高度相關性的AbilitySlice構成。如新聞瀏覽功能,包含兩個AbilitySlice:一個AbilitySlice用于展示新聞列表,另一個AbilitySlice用于展示新聞詳情。它們就是總和分的設計模式,關系如下圖4.1所示:

          圖4.1 Page與AbilitySlice

          雖然一個Ability可以包含多個AbilitySlice,但是Ability進入前臺時界面默認只展示一個AbilitySlice。Ability用setMainRoute()方法啟動主AbilitySlice的代碼如下:

          package com.lc.hm.booking;
          
          import com.lc.hm.booking.slice.MainAbilitySlice;
          import ohos.aafwk.ability.Ability;
          import ohos.aafwk.content.Intent;
          
          public class MainAbility extends Ability {
              @Override
              public void onStart(Intent intent) {
                  super.onStart(intent);
                  //路由(打開)到主AbilitySlice
                  super.setMainRoute(MainAbilitySlice.class.getName());
              }
          }

          順著路由,找到slice下的MainAbilitySlice.java文件,打開之后,代碼如下所示,其中核心的代碼是setUIContent()這行加載布局文件的代碼,將這行代碼復制出來并粘貼到MainAbility.java文件中。

          super.setUIContent(ResourceTable.Layout_ability_main);

          注釋MainAbility.java文件中的setMainRoute()所在行的代碼,加上從MainAbilitySlice.java文件復制過來的代碼,結果如下:

          package com.lc.hm.booking;
          
          import com.lc.hm.booking.slice.MainAbilitySlice;
          import ohos.aafwk.ability.Ability;
          import ohos.aafwk.content.Intent;
          
          public class MainAbility extends Ability {
              @Override
              public void onStart(Intent intent) {
                  super.onStart(intent);
                  //路由(打開)到主AbilitySlice
                  //super.setMainRoute(MainAbilitySlice.class.getName());
                  super.setUIContent(ResourceTable.Layout_ability_main);
              }
          }

          運行項目之后,你會發現效果和之前的是一模一樣的。

          由此說明AbilitySlice是可選的,只是在下面兩種情況時,用AbilitySlice更優:

          ①頁面有多種布局,需要對頁面進行動態布局,每種布局可以對應一個AbilitySlice;

          ②頁面有多個Tab選項卡,需要在多個Tab之間切換,每個Tab可以對應一個。

          而AbilitySlice用到的兩種情況,在開發App時是非常常見的,這就是鴻蒙App引入AbilitySlice的原因。用AbilitySlice,在同一個窗口中切換頁面,用Ability,彈出新窗口。

          六、Ability頁面,創建和加載布局

          要臉Ability的開發,占了鴻蒙App開發的大部分工作,所以你需要多花點時間研究,研究。再次打開MainAbility.java文件,左手按住鍵盤上的Ctrl鍵,右手將鼠標移到Layout_ability_main上,鼠標單擊之后,會打開一個ability_main.xml文件。

          super.setUIContent(ResourceTable.Layout_ability_main);

          從ability_main.xml文件在layout目錄下,你應該能明白,它是一個專門用于布局的文件,其中DirectionalLayout為垂直方向的線性布局管理器,Text為文本控件,關于它們的詳細介紹,后面都會說到,此刻,你大概了解一下就好。

          <?xml version="1.0" encoding="utf-8"?>
          <DirectionalLayout
              xmlns:ohos="http://schemas.huawei.com/res/ohos"
              ohos:height="match_parent"
              ohos:width="match_parent"
              ohos:alignment="center"
              ohos:orientation="vertical">
          
              <Text
                  ohos:id="$+id:text_helloworld"
                  ohos:height="match_content"
                  ohos:width="match_content"
                  ohos:background_element="$graphic:background_ability_main"
                  ohos:layout_alignment="horizontal_center"
                  ohos:text="$string:mainability_HelloWorld"
                  ohos:text_size="40vp"
                  />
          
          </DirectionalLayout>

          鴻蒙實現頁面布局,有兩種方法:一種是用上面的xml文件進行布局,接著在Java類中用setUIContent()加載,紅線
          ResourceTable.Layout_ability_main由開發工具自動生成;還有一種方法就是通過Java代碼實現。

          在MainAbility.java類中用代碼實現布局如下所示,為了不讓你感覺到單調,我特意將文字改成了"你好,鴻蒙"。

          package com.lc.hm.booking;
          import ohos.aafwk.ability.Ability;
          import ohos.aafwk.content.Intent;
          import ohos.agp.components.DirectionalLayout;
          import ohos.agp.components.Text;
          import ohos.agp.utils.LayoutAlignment;
          import ohos.agp.components.DependentLayout.LayoutConfig;
          
          public class MainAbility extends Ability {
              @Override
              public void onStart(Intent intent) {
                  super.onStart(intent);
                  DirectionalLayout myLayout=new DirectionalLayout(this);
                  // 設置布局寬高
                  myLayout.setWidth(LayoutConfig.MATCH_PARENT);
                  myLayout.setHeight(LayoutConfig.MATCH_PARENT);
                  myLayout.setAlignment(LayoutAlignment.CENTER);
                  // 創建一個文本
                  Text text=new Text(this);
                  text.setText("你好,鴻蒙");
                  text.setWidth(LayoutConfig.MATCH_PARENT);
                  text.setTextSize(100);
                  // 設置文本的布局
                  DirectionalLayout.LayoutConfig textConfig=new DirectionalLayout.LayoutConfig(LayoutConfig.MATCH_CONTENT, LayoutConfig.MATCH_CONTENT);
                  text.setLayoutConfig(textConfig);
                  myLayout.addComponent(text);
                  super.setUIContent(myLayout);
              }
          }

          運行代碼之后,效果如下,和用xml布局是一樣的。

          雖然可以用Java代碼實現布局,但大家都不這樣用,除了工作量大,還是不好維護和擴展的問題,所以建議你開發鴻蒙App,也用xml布局的方式。

          七、Ability頁面,如何獲取資源

          鴻蒙App的資源,指的是resources目錄下的字符串、圖片和音頻等。資源獲取,說的是在Java類或布局文件XML中對字符串、圖片等的引用。

          resources目錄包括兩大類目錄,一類為base目錄與限定詞目錄,另一類為rawfile目錄。base目錄,通過指定資源類型(type)和資源名稱(name)來引用;rawfile目錄中的資源文件,通過指定文件路徑和文件名稱來引用。

          打開base/element下的string.json,你可以看到字符串是用鍵值對的方式進行定義的,代碼如下所示:

          {
            "string": [
              {
                "name": "entry_MainAbility",
                "value": "entry_MainAbility"
              },
              {
                "name": "mainability_description",
                "value": "Java_Empty Ability"
              },
              {
                "name": "mainability_HelloWorld",
                "value": "Hello World"
              }
            ]
          }

          在string.json文件中,添加一項內容,如下:

          {
            "name": "say",
            "value": "學鴻蒙App開發的人最帥"
          }

          重復代碼就不粘貼了,string.json完整內容如圖6.1所示。

          圖6.1 string.json

          在你按下保存代碼的一刻,開發工具會自動將"say"內容添加到ResourceTable類中,格式為ResourceTable.type_name,其中type為資源類型,如字符串:String;name為資源名稱,如"say"。

          1. 在Java類中,通過ResourceManager類獲取ResourceTable.String_say的value:"學鴻蒙App開發的人最帥",代碼(MainAbility.java文件中)示例如下:

          package com.lc.hm.booking;
          
          import ohos.aafwk.ability.Ability;
          import ohos.aafwk.content.Intent;
          import ohos.global.resource.ResourceManager;
          
          public class MainAbility extends Ability {
              @Override
              public void onStart(Intent intent) {
                  super.onStart(intent);
                  try {
                      ResourceManager resManager=this.getResourceManager();
                      String result=resManager
                        .getElement(ResourceTable.String_say).getString();
                      System.out.println(result);
                  } catch (Exception e) {
                      System.out.println("資源找不到");
                  }
              }
          }

          運行代碼之后,會在輸出窗口,看到如下內容:

          I/System.out: 學鴻蒙App開發的人最帥

          2. 在布局文件xml中,引用資源文件的格式:$type:name,其中,type為類型,如string(注意:首字母小寫),name為名稱,如"say",打開布局文件,調整如下:

          <?xml version="1.0" encoding="utf-8"?>
          <DirectionalLayout
              xmlns:ohos="http://schemas.huawei.com/res/ohos"
              ohos:height="match_parent"
              ohos:width="match_parent"
              ohos:alignment="center"
              ohos:orientation="vertical">
          
              <Text
                  ohos:height="match_content"
                  ohos:width="match_content"
                  ohos:text="$string:say"
                  ohos:text_size="30vp"
                  />
          
          </DirectionalLayout>

          打開MainAbility.java文件,內容調整如下:

          package com.lc.hm.booking;
          
          import ohos.aafwk.ability.Ability;
          import ohos.aafwk.content.Intent;
          
          
          public class MainAbility extends Ability {
              @Override
              public void onStart(Intent intent) {
                  super.onStart(intent);
                  super.setUIContent(ResourceTable.Layout_ability_main);
              }
          }

          運行虛擬機之后,你會在手機窗口中,看到如下效果:

          在java代碼或xml布局文件中調用base的資源,用法是一樣的,只是類型(如String、Media等)不同。

          對了,在json文件中,value的值可以是字符串、數字、布爾和數組類型。

          另外,如果你想使用原生的資源,那就將其(如demo.js文件)放在rawfile目錄下并在java代碼中進行調用,用法如下所示:

          ResourceManager resManager=this.getResourceManager();
          RawFileEntry rawFileEntry=resManager
            .getRawFileEntry("resources/rawfile/demo.js");

          八、頁面國際化

          鴻蒙系統,遲早會發布到全球的每個國家的,學鴻蒙App開發的你,趕緊掌握App實現國際化的功能,然后靜等花開。

          在鴻蒙系統啟動時,會有一種默認語言(如簡體中文),在打開App時,系統會自動匹配資源文件,如果系統是簡體中文,會匹配zh.element目錄(存放簡體中文)里的資源;如果是英文則會匹配en.element目錄(存放英文)里的資源。

          Java或xml文件,在中英文兩個目錄都找不到引用的資源時,會引用默認目錄element里的資源,如果連這里都沒有,App就會報錯。

          確定你的MainAbility.java文件內容是如下的內容:

          package com.lc.hm.booking;
          
          import ohos.aafwk.ability.Ability;
          import ohos.aafwk.content.Intent;
          
          
          public class MainAbility extends Ability {
              @Override
              public void onStart(Intent intent) {
                  super.onStart(intent);
                  super.setUIContent(ResourceTable.Layout_ability_main);
              }
          }

          確定layout里的ability_main.xml文件的內容如下:

          <?xml version="1.0" encoding="utf-8"?>
          <DirectionalLayout
              xmlns:ohos="http://schemas.huawei.com/res/ohos"
              ohos:height="match_parent"
              ohos:width="match_parent"
              ohos:alignment="center"
              ohos:orientation="vertical">
          
              <Text
                  ohos:height="match_content"
                  ohos:width="match_content"
                  ohos:text="$string:say"
                  ohos:text_size="30vp"
          
                  />
          
          </DirectionalLayout>

          打開zh.element里的string.json文件,添加如下內容:

          ,
          {
            "name": "say",
            "value": "鴻蒙App,學習中..."
          }

          打開en.element里的string.json文件,添加如下內容:

          ,
          {
            "name": "say",
            "value": "HarmonyOS App,studying."
          }

          運行項目,默認打開App的窗口如下:

          圖7.1 中文資源

          單擊中間前面兩個圖標的任意一個,滑到Home,找到【設置】圖標并單擊它,找到【系統和更新】--【語言和輸入法】--【語言和地區】--【添加語言】直接搜索English,單擊English所在行。選擇【更改】。

          再次回到Home,找到你開發的App(最后一個圖標就是),單擊打開它,你就會看到英文的內容了。你明白了嗎?明白的話,趕緊關注我,不明白的話,趕緊關注我。

          以上就是資源的國際化實現,除此之外,還有用Java代碼實現的日期格式化,示例如下:

          String languageTag="zh";
          String out=DateFormatUtil.format("EEEEdMMMMy", languageTag, 
                       "Asia/Shanghai", 0, 3600 * 1000); 

          電話號碼國際化:不同的區域的電話號碼有不同的格式化效果,當需要展示本地電話號碼時,應遵循當地電話號碼的格式化原則,示例代碼如下:

          Locale.Builder builder=new Locale.Builder();
          builder.setLanguage("zh");
          builder.setRegion("CN");
          builder.setScript("Hant");
          Locale locale=builder.build();
          String displayName=PhoneNumberAttribution
            .getAttribute("+8615611xxxxxx", "CN", locale); 

          度量衡格式化:提供了對度量衡國際化能力的支持,可支持度量衡體系和維度之間的轉換,與不同國家度量衡體系的自動轉換,示例代碼如下:

          Locale enUS=Locale.US;
          MeasureFormatter mes=MeasureFormatter.getInstance(enUS);
          mes.format(MeasureOptions.Unit.VOLUME_US_CUP,
          1000,
          MeasureOptions.Unit.VOLUME_SI_LITER,
          MeasureOptions.FormatStyle.WIDE));

          用Java代碼實現的國際化,不用記,也不用背,它們平時用得不多,需要時,再去查詢就好了。至于表示設備使用的語言類型(目錄名),由2~3個小寫字母組成。zh表示簡體中文,en表示英語,mai表示邁蒂利語,其他的,你可以查閱ISO 639(ISO制定的語言編碼標準)。

          九、Ability和AbilitySlice的生命周期

          用戶操作等行為均會引起頁面實例在其生命周期的不同狀態之間進行轉換,Ability類提供的回調機制能夠讓其感知外界的變化,從而執行不同的方法。生命周期的不同狀態轉換及其對應的回調,如圖8.1所示。

          圖 8.1 生命周期

          說白點,就是窗口(頁面),在啟動時,切換時,隱藏時,關閉時會執行對應的回調方法,方便程序員進行相關的處理。如關閉窗口時,進行資源釋放。

          onStart()方法

          首次創建頁面實例時,觸發該回調方法,在其生命周期過程中僅觸發一次。一般在此執行Ability的初始化工作,如加載布局模板。

          @Override
          public void onStart(Intent intent) {
              super.onStart(intent);
              super.setUIContent(ResourceTable.Layout_ability_main);
          }

          onActive()方法

          Ability可見且獲得用戶焦點能交互時系統會調用這個方法,在這可處理在onStart()之后的一些補充工作。

          @Override
          public void onActive() {
              
          }

          onInactive()方法

          Ability失去焦點時,系統將調用此回調,此后進入INACTIVE狀態。程序員可以在此回調中實現頁面在失去焦點時需要進行處理的業務,如保存臨時數據。

          @Override
          public void onInactive() {
          
          }

          onBackground()方法

          Ability不再對用戶可見時,系統將調用此回調,如用戶跳轉到其他窗口時,會隱藏這個Ability。程序員可以在此方法中釋放Ability不可見時無用的資源,或在此回調中執行較為耗時的狀態保存操作。

          @Override
          public void onBackground() {
          
          }

          onForeground()方法

          處于BACKGROUND狀態的Ability仍然駐留在內存中,當重新回到前臺時,如用戶導航到此Ability時,將會回調這個onForeground()。

          @Override
          public void onForeground(Intent intent) {
          
          }

          onStop()

          系統將要銷毀Ability時,將會觸發此回調函數,通知用戶進行系統資源的釋放。

          @Override
          public void onStop() {
          
          }

          以上方法告訴你,人到什么時候,就該做什么事,鴻蒙出來了,該學鴻蒙App開發時就學。否則將錯失良機。

          AbilitySlice作為Ability的組成單元,其生命周期是依托于其所屬Ability生命周期的。AbilitySlice和Page具有相同的生命周期狀態和同名的回調,當Ability生命周期發生變化時,它的AbilitySlice也會發生相同的生命周期變化,它與Ability的相應回調類似,因此不再贅述。

          回調方法,不是每一個都會被用到的,不用特意背記。在項目實戰時,你就能清楚地知道用到哪一些了。

          十、XML創建布局

          XML聲明布局的方式更加簡便直觀,是開發App的核心內容之一,咱們完全有必要搞清楚。每一個Component和ComponentContainer對象大部分屬性都支持在XML中進行設置,它們有各自的XML屬性,也有共同的屬性。

          這一節說一下組件共同的屬性,至于有"個性"的內容,在介紹具體組件時,再詳細講解。所有組件都有的屬性,如下:

          1. ID
          ohos:id="$+id:text"

          組件唯一編號,可用于區分不同的組件。尤其在DependentLayout布局中,組件之間需要描述相對位置關系,描述時要通過ID來指定對應組件。

          Java類中,是通過組件ID,查找組件的,如果ID名相同,會返回第一個組件,因此你要保證ID的唯一性,避免出現與預期不符合的問題。

          2. 布局參數

          為必選屬性,值可為數字,也可為match_parent等。

          ohos:width="20vp"
          ohos:height="10vp"

          具體的數值:10(以像素為單位)、10vp(以屏幕相對像素為單位)。

          match_parent:表示組件大小將擴展為父組件允許的最大值,它將占據父組件方向上的剩余大小;

          match_content:表示組件大小與它的內容占據的大小范圍相適應。

          ohos:min_width="10vp"
          ohos:min_height="8vp"

          min_width用于調整組件的最小寬度,min_height用于調整組件的最高度。

          3. 前景背景

          值可為圖片,也可以為顏色值。

          ohos:background_element="$media:bg"
          ohos:foreground_element="#FFFFFF"

          找一張背景圖,放到media目錄下,并在ability_main.xml文件中進行引用,運行虛擬機之后,效果如下:

          4. 邊距

          外邊距:清除周圍的(外邊框)元素區域,沒有背景顏色,是完全透明的。

           ohos:margin="10vp"

          margin 可以一次性改變所有上下左右的外邊距。如果要單獨設置某個外邊距,可用如下中的一個或多個。

          ohos:top_margin="10vp"
          ohos:bottom_margin="10vp"
          ohos:left_margin="10vp"
          ohos:right_margin="10vp"

          內邊距:用于在任何定義的邊界內的元素內容周圍生成空間。

          ohos:padding="8vp"

          padding可以一次性改變所有上下左右的內邊距。如果要單獨設置某個內邊距,可用如下中的一個或多個。

          ohos:top_padding="8vp"
          ohos:bottom_padding="8vp"
          ohos:left_padding="8vp"
          ohos:right_padding="8vp"

          外邊距和內邊距的示意圖如下所示:

          十一、App線性布局

          DirectionalLayout是Java UI中的一種重要組件布局,用于將一組組件(Component)按照水平或者垂直方向排布,能夠方便地對齊布局內的組件,布局之間可以互相嵌套使用。

          DirectionalLayout使用orientation設置布局內組件的排列方式,值為horizontal時,表示水平方向布局;為vertical時,表示表示垂直方向布局。

          ohos:orientation="horizontal"
          ohos:orientation="vertical"

          除了orientation屬性之外,還有一個用于對齊布局內組件的alignment屬性,它的可選值如下表所示:

          取值

          取值說明

          使用案例

          left

          左對齊

          可以設置取值項如表中所列,也可以使用“|”進行多項組合。

          ohos:alignment="top|left"

          ohos:alignment="left"

          top

          頂部對齊

          right

          右對齊

          bottom

          底部對齊

          horizontal_center

          水平居中對齊

          vertical_center

          垂直居中對齊

          center

          居中對齊

          start

          靠起始端對齊

          end

          靠結束端對齊

          在一個垂直vertical方向的DirectionalLayout里嵌套兩個水平horizontal方向的DirectionalLayout,兩個水平方向布局管理器里都有一張圖標和文字說明,為了打扮得更好看,我用Component實現了分割線,代碼如下:

          <?xml version="1.0" encoding="utf-8"?>
          <DirectionalLayout
              xmlns:ohos="http://schemas.huawei.com/res/ohos"
              ohos:height="match_parent"
              ohos:width="match_parent"
              ohos:alignment="vertical_center"
              ohos:background_element="$media:bg"
              ohos:orientation="vertical">
          
              <Component
                  ohos:height="1vp"
                  ohos:width="match_content"
                  ohos:alignment="left|center"
                  ohos:background_element="#FFFFFF"/>
          
              <DirectionalLayout
                  ohos:height="match_content"
                  ohos:width="match_content"
                  ohos:alignment="left|center"
                  ohos:bottom_margin="20vp"
                  ohos:left_margin="10vp"
                  ohos:orientation="horizontal"
                  ohos:top_margin="20vp">
          
                  <Image
                      ohos:height="match_content"
                      ohos:width="match_content"
                      ohos:image_src="$media:sm"/>
          
                  <Text
                      ohos:height="match_content"
                      ohos:width="match_content"
                      ohos:left_padding="5vp"
                      ohos:text="掃碼"
                      ohos:text_color="#FFFFFF"
                      ohos:text_size="25vp"/>
              </DirectionalLayout>
          
              <Component
                  ohos:height="1vp"
                  ohos:width="match_content"
                  ohos:alignment="left|center"
                  ohos:background_element="#FFFFFF"/>
          
              <DirectionalLayout
                  ohos:height="match_content"
                  ohos:width="match_content"
                  ohos:alignment="left|center"
                  ohos:bottom_margin="20vp"
                  ohos:left_margin="10vp"
                  ohos:orientation="horizontal"
                  ohos:top_margin="20vp">
          
                  <Image
                      ohos:height="match_content"
                      ohos:width="match_content"
                      ohos:image_src="$media:pz"/>
          
                  <Text
                      ohos:height="match_content"
                      ohos:width="match_content"
                      ohos:left_padding="5vp"
                      ohos:text="拍照"
                      ohos:text_color="#FFFFFF"
                      ohos:text_size="25vp"/>
              </DirectionalLayout>
          
              <Component
                  ohos:height="1vp"
                  ohos:width="match_content"
                  ohos:alignment="left|center"
                  ohos:background_element="#FFFFFF"/>
          </DirectionalLayout>

          運行鴻蒙P40虛擬機之后,效果如下所示:

          圖10.1 垂直和水平布局

          DirectionalLayout里的組件的對齊方式,在ohos:alignment的指定下是保持一致的,如果想要改變個別組件的對齊方式,你可以在組件里,用layout_alignment屬性進行調整,它的可選值,如下表所示:

          取值

          取值說明

          使用案例

          left

          左對齊

          可以設置取值項如表中所列,也可以使用“|”進行多項組合。

          ohos:layout_alignment="top"

          ohos:layout_alignment="top|left"

          top

          頂部對齊

          right

          右對齊

          bottom

          底部對齊

          horizontal_center

          水平居中對齊

          vertical_center

          垂直居中對齊

          center

          居中對齊

          DirectionalLayout中的組件使用layout_alignment控制自身在布局中的對齊方式,當對齊方式與排列方式方向一致時,對齊方式不會生效,如設置了水平方向的排列方式,則左對齊、右對齊將不會生效。

          <DirectionalLayout
              xmlns:ohos="http://schemas.huawei.com/res/ohos"
              ohos:height="match_parent"
              ohos:width="match_parent"
              ohos:alignment="vertical_center"
              ohos:background_element="$media:bg">
          
              <Text
                  ohos:height="match_content"
                  ohos:width="match_content"
                  ohos:layout_alignment="left"
                  ohos:text="程序猿"
                  ohos:text_color="#FFFFFF"
                  ohos:text_size="20vp"/>
          
              <Text
                  ohos:height="match_content"
                  ohos:width="match_content"
                  ohos:layout_alignment="horizontal_center"
                  ohos:text="程序媛"
                  ohos:text_color="#FFFFFF"
                  ohos:text_size="20vp"/>
          
              <Text
                  ohos:height="match_content"
                  ohos:width="match_content"
                  ohos:layout_alignment="right"
                  ohos:text="都是敲代碼的"
                  ohos:text_color="#FFFFFF"
                  ohos:text_size="20vp"/>
          </DirectionalLayout>

          運行效果如下所示:

          圖10.2 layout_alignment

          好了,到這,你可以先歇口氣,關注我之后,再接著往下看,下面還有更重要的內容,那就是組件的權重比。在DirectionalLayout中,用total_weight指定所有子視圖的權重之和,在子組件(如Text)中,用weight指定比重。

          total_weight的值如下表所示:

          取值

          取值說明

          使用案例

          float類型

          可以直接設置浮點數值,也可以引用float浮點數資源。

          ohos:total_weight="2.5"

          ohos:total_weight="$float:total_weight"

          weight的值如下所示:

          取值

          取值說明

          使用案例

          float類型

          可以直接設置浮點數值,

          也可以引用float浮點數資源。

          ohos:weight="1"

          ohos:weight="$float:weight"

          仔細觀察如下代碼,你會發現并沒有total_weight屬性存在,因為它是可選的,而不是必須的;另外,在組件里用weight屬性指定比重時,需要將width置為0。

          <DirectionalLayout
              xmlns:ohos="http://schemas.huawei.com/res/ohos"
              ohos:height="match_parent"
              ohos:width="match_parent"
              ohos:alignment="vertical_center"
              ohos:background_element="$media:bg"
              ohos:orientation="horizontal">
          
              <Text
                  ohos:height="50vp"
                  ohos:width="0vp"
                  ohos:background_element="#000fff"
                  ohos:text="學鴻蒙"
                  ohos:text_alignment="center"
                  ohos:text_size="20vp"
                  ohos:weight="1"/>
          
              <Text
                  ohos:height="50vp"
                  ohos:width="0vp"
                  ohos:background_element="#ff00ff"
                  ohos:text="App的人"
                  ohos:text_alignment="center"
                  ohos:text_size="20vp"
                  ohos:weight="1"/>
          
              <Text
                  ohos:height="50vp"
                  ohos:width="0vp"
                  ohos:text="最酷......"
                  ohos:text_alignment="center"
                  ohos:background_element="#ffff00"
                  ohos:text_size="20vp"
                  ohos:weight="1"/>
          </DirectionalLayout>

          在P40虛擬機運行的效果如下所示:

          十二、相對布局
          相對布局DependentLayout,也是比較常用的一個布局管理器,在它里面,組件的排列方式是相對于其他同級組件或者父組件的位置進行布局。

          1. 相對同級組件

          組件B神,想躲在組件A卡的后邊時,在B神中用end_of屬性指定A卡的身份id即可。你將end_of理解成追尾就好,也就是說,如果想讓B在A的尾部,可在組件B神中,用end_of屬性指定組件A的id名稱,代碼如下:

          <DependentLayout
              xmlns:ohos="http://schemas.huawei.com/res/ohos"
              ohos:height="match_parent"
              ohos:width="match_parent"
              ohos:background_element="$media:bg">
          
              <Text
                  ohos:id="$+id:a"
                  ohos:height="match_content"
                  ohos:width="match_content"
                  ohos:background_element="#EC9DAA"
                  ohos:margin="10vp"
                  ohos:padding="10vp"
                  ohos:text="我是A卡"
                  ohos:text_size="18fp"/>
          
              <Text
                  ohos:id="$+id:b"
                  ohos:end_of="$id:a"
                  ohos:height="match_content"
                  ohos:width="match_content"
                  ohos:background_element="#EC9DFF"
                  ohos:margin="10vp"
                  ohos:padding="10vp"
                  ohos:text="我是B神,躲在A后邊"
                  ohos:text_size="18fp"/>
          </DependentLayout>

          運行虛擬機之后,效果如下圖所示:

          有在尾部的end_of,就有在前面的start_of,還有在左邊的left_of等等,更多用于指定相對位置的屬性,如下表所示:

          屬性名稱

          中文描述

          取值

          取值說明

          使用案例

          left_of

          將右邊緣與另一個子組件的左邊緣對齊

          引用

          僅可引用DependentLayout中包含的其他組件的id。

          說明

          • left_of與start_of、end_of屬性有沖突,不建議一起使用。在“水平布局方向為從左到右”時,left_of會與start_of屬性沖突;在“水平布局方向為從右到左”時,left_of會與end_of屬性沖突。
          • 同時配置時,start_of、end_of優先級高于left_of屬性。

          ohos:left_of="$id:component_id"

          right_of

          將左邊緣與另一個子組件的右邊緣對齊

          引用

          僅可引用DependentLayout中包含的其他組件的id。

          說明

          • right_of與start_of、end_of屬性有沖突,不建議一起使用。在“水平布局方向為從左到右”時,right_of會與end_of屬性沖突;在“水平布局方向為從右到左”時,right_of會與start_of屬性沖突。
          • 同時配置時,start_of、end_of優先級高于right_of屬性。

          ohos:right_of="$id:component_id"

          start_of

          將結束邊與另一個子組件的起始邊對齊

          引用

          僅可引用DependentLayout中包含的其他組件的id。

          說明

          • start_of與left_of、right_of屬性有沖突,不建議一起使用。在“水平布局方向為從左到右”時,start_of會與left_of屬性沖突;在“水平布局方向為從右到左”時,start_of會與right_of屬性沖突。
          • 同時配置時,start_of優先級高于left_of、right_of屬性。

          ohos:start_of="$id:component_id"

          end_of

          將起始邊與另一個子組件的結束邊對齊

          引用

          僅可引用DependentLayout中包含的其他組件的id。

          說明

          • end_of與left_of、right_of屬性有沖突,不建議一起使用。在“水平布局方向為從左到右”時,end_of會與right_of屬性沖突;在“水平布局方向為從右到左”時,end_of會與left_of屬性沖突。
          • 同時配置時,end_of優先級高于left_of、right_of屬性。

          ohos:end_of="$id:component_id"

          above

          將下邊緣與另一個子組件的上邊緣對齊

          引用

          僅可引用DependentLayout中包含的其他組件的id

          ohos:above="$id:component_id"

          below

          將上邊緣與另一個子組件的下邊緣對齊

          引用

          僅可引用DependentLayout中包含的其他組件的id

          ohos:below="$id:component_id"

          align_baseline

          將子組件的基線與另一個子組件的基線對齊

          引用

          僅可引用DependentLayout中包含的其他組件的id

          ohos:align_baseline="$id:component_id"

          align_left

          將左邊緣與另一個子組件的左邊緣對齊

          引用

          僅可引用DependentLayout中包含的其他組件的id。

          說明

          • align_left與align_start、align_end屬性有沖突,不建議一起使用。在“水平布局方向為從左到右”時,align_left會與align_start屬性沖突;在“水平布局方向為從右到左”時,align_left會與align_end屬性沖突。
          • 同時配置時,align_start、align_end優先級高于align_left屬性。

          ohos:align_left="$id:component_id"

          align_top

          將上邊緣與另一個子組件的上邊緣對齊

          引用

          僅可引用DependentLayout中包含的其他組件的id

          ohos:align_top="$id:component_id"

          align_right

          將右邊緣與另一個子組件的右邊緣對齊

          引用

          僅可引用DependentLayout中包含的其他組件的id。

          說明

          • align_right與align_start、align_end屬性有沖突,不建議一起使用。在“水平布局方向為從左到右”時,align_right會與align_end屬性沖突;在“水平布局方向為從右到左”時,align_right會與align_start屬性沖突。
          • 同時配置時,align_start、align_end優先級高于align_right屬性。

          ohos:align_right="$id:component_id"

          align_bottom

          將底邊與另一個子組件的底邊對齊

          引用

          僅可引用DependentLayout中包含的其他組件的id

          ohos:align_bottom="$id:component_id"

          align_start

          將起始邊與另一個子組件的起始邊對齊

          引用

          僅可引用DependentLayout中包含的其他組件的id。

          說明

          • align_start與align_left、align_right屬性有沖突,不建議一起使用。在“水平布局方向為從左到右”時,align_start會與align_left屬性沖突;在“水平布局方向為從右到左”時,align_start會與align_right屬性沖突。
          • 同時配置時,align_start優先級高于align_left、align_right屬性。

          ohos:align_start="$id:component_id"

          align_end

          將結束邊與另一個子組件的結束邊對齊

          引用

          僅可引用DependentLayout中包含的其他組件的id。

          說明

          • align_end與align_left、align_right屬性有沖突,不建議一起使用。在“水平布局方向為從左到右”時,align_end會與align_right屬性沖突;在“水平布局方向為從右到左”時,align_end會與align_left屬性沖突。
          • 同時配置時,align_end優先級高于align_left、align_right屬性。

          ohos:align_end="$id:component_id"

          align_parent_left

          將左邊緣與父組件的左邊緣對齊

          boolean類型

          可以直接設置true/false,也可以引用boolean資源。

          說明

          • align_parent_left與align_parent_start、align_parent_end屬性有沖突,不建議一起使用。在“水平布局方向為從左到右”時,align_parent_left會與align_parent_start屬性沖突;在“水平布局方向為從右到左”時,align_parent_left會與align_parent_end屬性沖突。
          • 同時配置時,align_parent_start、align_parent_end優先級高于align_parent_left屬性。

          ohos:align_parent_left="true"

          ohos:align_parent_left="$boolean:true"

          align_parent_top

          將上邊緣與父組件的上邊緣對齊

          boolean類型

          可以直接設置true/false,也可以引用boolean資源。

          ohos:align_parent_top="true"

          ohos:align_parent_top="$boolean:true"

          align_parent_right

          將右邊緣與父組件的右邊緣對齊

          boolean類型

          可以直接設置true/false,也可以引用boolean資源。

          說明

          • align_parent_right與align_parent_start、align_parent_end屬性有沖突,不建議一起使用。在“水平布局方向為從左到右”時,align_parent_right會與align_parent_end屬性沖突;在“水平布局方向為從右到左”時,align_parent_right會與align_parent_start屬性沖突。
          • 同時配置時,align_parent_start、align_parent_end優先級高于align_parent_right屬性。

          ohos:align_parent_right="true"

          ohos:align_parent_right="$boolean:true"

          align_parent_bottom

          將底邊與父組件的底邊對齊

          boolean類型

          可以直接設置true/false,也可以引用boolean資源。

          ohos:align_parent_bottom="true"

          ohos:align_parent_bottom="$boolean:true"

          align_parent_start

          將起始邊與父組件的起始邊對齊

          boolean類型

          可以直接設置true/false,也可以引用boolean資源。

          說明

          • align_parent_start與align_parent_left、align_parent_right屬性有沖突,不建議一起使用。在“水平布局方向為從左到右”時,align_parent_start會與align_parent_left屬性沖突;在“水平布局方向為從右到左”時,align_parent_start會與align_parent_right屬性沖突。
          • 同時配置時,align_parent_start優先級高于align_parent_left、align_parent_right屬性。

          ohos:align_parent_start="true"

          ohos:align_parent_start="$boolean:true"

          align_parent_end

          將結束邊與父組件的結束邊對齊

          boolean類型

          可以直接設置true/false,也可以引用boolean資源。

          說明

          • align_parent_end與align_parent_left、align_parent_right屬性有沖突,不建議一起使用。在“水平布局方向為從左到右”時,align_parent_end會與align_parent_right屬性沖突;在“水平布局方向為從右到左”時,align_parent_end會與align_parent_left屬性沖突。
          • 同時配置時,align_parent_end優先級高于align_parent_left、align_parent_right屬性。

          ohos:align_parent_end="true"

          ohos:align_parent_end="$boolean:true"

          center_in_parent

          將子組件保持在父組件的中心

          boolean類型

          可以直接設置true/false,也可以引用boolean資源。

          ohos:center_in_parent="true"

          ohos:center_in_parent="$boolean:true"

          horizontal_center

          將子組件保持在父組件水平方向的中心

          boolean類型

          可以直接設置true/false,也可以引用boolean資源。

          ohos:horizontal_center="true"

          ohos:horizontal_center="$boolean:true"

          vertical_center

          將子組件保持在父組件垂直方向的中心

          boolean類型

          可以直接設置true/false,也可以引用boolean資源。

          ohos:vertical_center="true"

          ohos:vertical_center="$boolean:true"

          2. 相對父級組件

          內部組件相對于外部組件的位置,如內部組件A在外部組件B的左上角,將align_parent_top設置為True即可。組件的位置布局可以進行組合,形成處于左上角、左下角、右上角、右下角的布局。

          代碼示例如下所示:

          <DependentLayout
              xmlns:ohos="http://schemas.huawei.com/res/ohos"
              ohos:height="match_parent"
              ohos:width="match_parent"
              ohos:background_element="$media:bg">
          
              <Text
                  ohos:id="$+id:b"
                  ohos:height="match_content"
                  ohos:width="match_content"
                  ohos:align_parent_top="true"
                  ohos:background_element="#EC9DFF"
                  ohos:margin="10vp"
                  ohos:padding="10vp"
                  ohos:text="我是程序猿,我在左上角飄揚"
                  ohos:text_size="18fp"/>
          </DependentLayout>
          

          運行虛擬機之后的效果如下圖所示:

          十三、表格布局

          在開發鴻蒙App時,大多數情況下,用線性布局DirectionalLayout相對布局DependentLayout就可以搞定的。這兩種布局之前講過了,下面就介紹一下另外的4種布局。

          在需要對組團組件進行布局時,可以用表格布局TableLayout盒子布局AdaptiveBoxLayout進行排版,至于絕對布局PositionLayout和層疊布局StackLayout,平時很少會用到。下面就一起來了解一下這4種新的布局。

          表格布局

          表格布局TableLayout按行和列的方式進行布局,這個在布局多個組件時,會用到,它的相關屬性如下表所示:

          屬性名稱

          中文描述

          取值

          取值說明

          使用案例

          alignment_type

          對齊方式

          align_edges

          表示TableLayout內的組件按邊界對齊。

          ohos:alignment_type="align_edges"

          align_contents

          表示TableLayout內的組件按邊距對齊。

          ohos:alignment_type="align_contents"

          column_count

          列數

          integer類型

          可以直接設置整型數值,也可以引用integer資源。

          ohos:column_count="3"

          ohos:column_count="$integer:count"

          row_count

          行數

          integer類型

          可以直接設置整型數值,也可以引用integer資源。

          ohos:row_count="2"

          ohos:row_count="$integer:count"

          orientation

          排列方向

          horizontal

          表示水平方向布局。

          ohos:orientation="horizontal"

          vertical

          表示垂直方向布局。

          ohos:orientation="vertical"

          示例代碼如下所示:

          <?xml version="1.0" encoding="utf-8"?>
          <TableLayout
              xmlns:ohos="http://schemas.huawei.com/res/ohos"
              ohos:height="match_parent"
              ohos:width="match_parent"
              ohos:background_element="#e8ebf4"
              ohos:column_count="2"
              ohos:layout_alignment="horizontal_center"
              ohos:padding="8vp"
              ohos:row_count="2">
          
              <Text
                  ohos:height="60vp"
                  ohos:width="60vp"
                  ohos:margin="8vp"
                  ohos:text="酷的"
                  ohos:text_alignment="center"
                  ohos:text_color="#4dd3a0"
                  ohos:text_size="30fp"/>
          
              <Text
                  ohos:height="60vp"
                  ohos:width="60vp"
                  ohos:margin="8vp"
                  ohos:text="美的"
                  ohos:text_alignment="center"
                  ohos:text_color="#fe6486"
                  ohos:text_size="30fp"/>
          
              <Text
                  ohos:height="60vp"
                  ohos:width="60vp"
                  ohos:margin="8vp"
                  ohos:text="帥的"
                  ohos:text_alignment="center"
                  ohos:text_color="#0099fb"
                  ohos:text_size="30fp"/>
          
              <Text
                  ohos:height="60vp"
                  ohos:width="200vp"
                  ohos:margin="8vp"
                  ohos:text="都是關注我的"
                  ohos:text_alignment="center"
                  ohos:text_color="#fc7754"
                  ohos:text_size="30fp"/>
          </TableLayout>

          虛擬機運行的效果如下所示:

          十四、盒子布局

          盒子布局AdaptiveBoxLayout是自適應盒子布局,該布局提供了在不同屏幕尺寸設備上的自適應布局能力,主要用于相同級別的多個組件需要在不同屏幕尺寸設備上自動調整列數的場景。常用于多個組件一起橫向或縱向布局。

          1. 該布局中的每個子組件都用一個單獨的“盒子”裝起來,子組件設置的布局參數都是以盒子作為父布局生效,不以整個自適應布局為生效范圍。
          2. 該布局中每個盒子的寬度固定為布局總寬度除以自適應得到的列數,高度為match_content,每一行中的所有盒子按高度最高的進行對齊。
          3. 該布局水平方向是自動分塊,因此水平方向不支持match_content,布局水平寬度僅支持match_parent或固定寬度。
          4. 自適應僅在水平方向進行了自動分塊,縱向沒有做限制,因此如果某個子組件的高設置為match_parent類型,可能導致后續行無法顯示。

          代碼示例如下:

          <DirectionalLayout
              xmlns:ohos="http://schemas.huawei.com/res/ohos"
              ohos:height="match_parent"
              ohos:width="match_parent"
              ohos:background_element="#f9b958"
              ohos:orientation="vertical">
          
              <AdaptiveBoxLayout
                  xmlns:ohos="http://schemas.huawei.com/res/ohos"
                  ohos:id="$+id:adaptive_box_layout"
                  ohos:height="0vp"
                  ohos:width="match_parent"
                  ohos:weight="1">
          
                  <Text
                      ohos:height="40vp"
                      ohos:width="match_parent"
                      ohos:background_element="#69ddac"
                      ohos:margin="10vp"
                      ohos:padding="10vp"
                      ohos:text="鴻蒙App"
                      ohos:text_size="18fp"/>
          
                  <Text
                      ohos:height="40vp"
                      ohos:width="match_parent"
                      ohos:background_element="#0a8bf0"
                      ohos:margin="10vp"
                      ohos:padding="10vp"
                      ohos:text="Android App"
                      ohos:text_size="18fp"/>
          
                  <Text
                      ohos:height="40vp"
                      ohos:width="match_parent"
                      ohos:background_element="#8345fe"
                      ohos:margin="10vp"
                      ohos:padding="10vp"
                      ohos:text="iOS App"
                      ohos:text_size="18fp"/>
              </AdaptiveBoxLayout>
          
              <Text
                  ohos:height="40vp"
                  ohos:width="match_parent"
                  ohos:background_element="#fc7756"
                  ohos:margin="10vp"
                  ohos:padding="10vp"
                  ohos:text="有你的關注,離用專欄發布就近了"
                  ohos:text_size="18fp"/>
          
          </DirectionalLayout>

          在虛擬機下運行的效果,美美的

          盒子布局在開發中,有時會用到,你熟悉一下即可。

          十五、絕對和層疊布局

          絕對布局PositionLayout中,子組件通過指定準確的x/y坐標值在屏幕上顯示。(0, 0)為左上角;當向下或向右移動時,坐標值變大;允許組件之間互相重疊。這個布局,在開發中很少用到,知道有這個布局存在即可。

          層疊布局

          層疊布局StackLayout直接在屏幕上開辟出一塊空白的區域,添加到這個布局中的視圖都是以層疊的方式顯示,而它會把這些視圖默認放到這塊區域的左上角,第一個添加到布局中的視圖顯示在最底層,最后一個被放在最頂層。上一層的視圖會覆蓋下一層的視圖。

          它偶爾會用在效果切換上,我之前開發過不少App,印象當中也是沒用到這個布局管理器。

          這兩個布局,平時很少用到,只要知道有它們的存在就好了

          量限制 (rate-limiting),我們可以用來限制用戶在給定時間內HTTP請求的數量。流量限制可以用作安全目的,比如可以減慢暴力密碼破解的速率。還可以用來抵御 DDOS 攻擊。更常見的情況是該功能被用來保護上游應用服務器不被同時太多用戶請求所壓垮。

          1、Nginx如何限流

          Nginx的”流量限制”使用漏桶算法(leaky bucket algorithm),就好比,一個桶口在倒水,桶底在漏水的水桶。如果桶口倒水的速率大于桶底的漏水速率,桶里面的水將會溢出;同樣,在請求處理方面,水代表來自客戶端的請求,水桶代表根據”先進先出調度算法”(FIFO)等待被處理的請求隊列,桶底漏出的水代表離開緩沖區被服務器處理的請求,桶口溢出的水代表被丟棄和不被處理的請求。

          2、配置基本的限流

          “流量限制”配置兩個主要的指令,limit_req_zonelimit_req,如下所示:

          limit_req_zone $binary_remote_addr zone=mylimit:10m rate=1r/s;
                  upstream myweb {
                          server 10.0.105.196:80 weight=1 max_fails=1 fail_timeout=1;
                          }
                  server {
                          listen 80;
                          server_name localhost;
          
                          location /login {
                                  limit_req zone=mylimit;
                                  proxy_pass http://myweb;
                                  proxy_set_header Host $host:$server_port;
                                  proxy_set_header X-Real-IP $remote_addr;
                                  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                                  }
                  }
          10.0.105.196配置:
          server {
                  listen 80;
                  server_name localhost;
                  location /login {
                          root    /usr/share/nginx/html;
                          index   index.html index.html;
                          }
          }

          limit_req_zone指令設置流量限制和內存區域的參數,但實際上并不限制請求速率。所以需要通過添加limit_req指令啟用流量限制,應用在特定的location或者server塊。(示例中,對于”/login/”的所有請求)。

          limit_req_zone指令通常在HTTP塊中定義,使其可在多個上下文中使用,它需要以下三個參數:

          • Key - 定義應用限制的請求特性。示例中的 Nginx 變量$binary_remote_addr,保存客戶端IP地址的二進制形式。
          • Zone - 定義用于存儲每個IP地址狀態以及被限制請求URL訪問頻率的內存區域。通過zone=keyword標識區域的名字(自定義),以及冒號后面跟區域大小。16000個IP地址的狀態信息,大約需要1MB。
          • Rate - 連接請求。在示例中,速率不能超過每秒1個請求。

          4、發送到客戶端的錯誤代碼

          一般情況下,客戶端超過配置的流量限制時,Nginx響應狀態碼為503(Service Temporarily Unavailable)。可以使用limit_req_status指令來設置為其它狀態碼(例如下面的404狀態碼):

          limit_req_zone $binary_remote_addr zone=mylimit:10m rate=1r/s;
              upstream myweb {
                      server 10.0.105.196:80 weight=1 max_fails=1 fail_timeout=1;
                  }
              server {
                      listen 80;
                      server_name localhost;
                  
                      location /login {
                      limit_req zone=mylimit;
                      limit_req_status 404;
                              proxy_pass http://myweb;
                                  proxy_set_header Host $host:$server_port;
                              proxy_set_header X-Real-IP $remote_addr;
                              proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                              }
              }

          18、nginx 訪問控制

          1、nginx 訪問控制模塊

          (1)基于IP的訪問控制:http_access_module (2)基于用戶的信任登錄:http_auth_basic_module

          2、基于IP的訪問控制

          1、配置語法

          Syntax:allow address | CIDR | unix: | all;
          default:默認無
          Context:http,server,location
          ?
          Syntax:deny address | CIDR | unix: | all;
          default:默認無
          Context:http,server,location===================================================allow    允許     //ip或者網段
          deny    拒絕     //ip或者網段

          2、配置測試

          編輯/etc/nginx/conf.d/access_mod.conf內容如下:

          [root@192 ~]# vim /etc/nginx/conf.d/access_mod.conf
          server {
                  listen 80;
                  server_name localhost;
                  location  / {
                          root /usr/share/nginx/html;
                          index index.html index.hml;
                          deny 192.168.1.8;
                          allow all;
                          }
          }
          [root@192 ~]# nginx -t
          [root@192 ~]# nginx -s reload
          ?
          #需要注意:
          1.按順序匹配,已經被匹配的ip或者網段,后面不再被匹配。
          2.如果先允許所有ip訪問,在定義拒絕訪問。那么拒絕訪問不生效。
          3.默認為allow all

          宿主機IP為192.168.1.8,虛擬機IP為192.168.1.11,故這里禁止宿主機訪問,允許其他所有IP訪問。 宿主機訪問http://192.168.1.11,顯示403 Forbidden。 當然也可以反向配置,同時也可以使用IP網段的配置方式,如allow 192.168.1.0/24;,表示滿足此網段的IP都可以訪問。

          3、指定location拒絕所有請求

          如果你想拒絕某個指定URL地址的所有請求,只需要在location塊中配置deny all指令:

          [root@192 ~]# vim /etc/nginx/conf.d/access_mod.conf
          server {
                  listen 80;
                  server_name localhost;
                  location  / {
                          root /usr/share/nginx/html;
                          index index.html index.hml;
                          deny all;    #拒絕所有
                          }
          }
          ?
          [root@192 ~]# nginx -t
          [root@192 ~]# nginx -s reload

          3、基于用戶的信任登錄

          (2)基于用戶的信任登錄模塊:http_auth_basic_module

          有時我們會有這么一種需求,就是你的網站的某些頁面不希望公開,我們希望的是某些特定的客戶端可以訪問。那么我們可以在訪問時要求進行身份認證,就如給你自己的家門加一把鎖,以拒絕那些不速之客。

          1、配置語法

          Syntax:auth_basic string | off;
          default:auth_basic off;
          Context:http,server,location
          ?
          Syntax:auth_basic_user_file file;
          default:默認無
          Context:http,server,location
          file:存儲用戶名密碼信息的文件。

          2、配置示例

          [root@192 ~]# vim /etc/nginx/conf.d/auth_mod.conf 
          server {
              listen 80;
              server_name localhost;
              location ~ /admin {
                  root /var/www/html;
                  index index.html index.hml;
                  auth_basic "Auth access test!";
                  auth_basic_user_file /etc/nginx/auth_conf;
                  }
          }
          ?
          [root@192 ~]# nginx -t
          [root@192 ~]# nginx -s reload
          [root@192 ~]# mkdir /var/www/html    #創建目錄
          [root@192 ~]# vim /var/www/html/index.html    #創建文件

          auth_basic不為off,開啟登錄驗證功能,auth_basic_user_file加載賬號密碼文件。

          3、建立口令文件

          [root@192 ~]# yum install -y httpd-tools #htpasswd 是開源 http 服務器 apache httpd 的一個命令工具,用于生成 http 基本認證的密碼文件
          [root@192 ~]# htpasswd -cm /etc/nginx/auth_conf user10 # -c 創建解密文件,-m MD5加密
          [root@192 ~]# htpasswd -m /etc/nginx/auth_conf user20
          [root@192 ~]# cat /etc/nginx/auth_conf 
          user10:$apr1$MOa9UVqF$RlYRMk7eprViEpNtDV0n40
          user20:$apr1$biHJhW03$xboNUJgHME6yDd17gkQNb0

          4、訪問測試

          轉自:知乎千鋒云計算學院

          么是html?

          html是一種簡單易記,功能強大的標記語言,它是學習前端知識的第一站,也是所有WEB開發者、乃至產品經理、運營人員必須學習的一項基礎內容。

          為什么學習html5?

          1. html5是WEB開發者,必須掌握的基礎知識;

          2. html5應用廣泛,它可以用來開發網站、WEB應用、WEB游戲等等,如微信小程序、移動端小游戲等都跟html5有關;

          3. html5很容易掌握,花幾個小時就可以掌握它;

          課程特點

          1. 講師講課風格幽默,整個學習過程輕松有趣,不枯燥、不乏味;

          2. 以就業為導向,與實戰相結合,滿足大部分學員的學習需求;

          學習建議

          1. 學完每一節課程,動手將代碼打一遍;

          2. 舉一反三,學完每節課程,思考一下它的應用場景;

          3. 完成本門課程,試著自己寫一個純html5的網頁;

          適宜人群

          1. 零基礎學員;

          2. 前端愛好者;

          1、DOCTYPE 描述文檔的類型,規定web 瀏覽器關于頁面使用哪個 HTML 版本進行編寫的指令。

          網頁可以使用的具體版本,網頁中可以使用那些標記,每個版本的DTD版本均有不同

          2、<html></html> 網頁文檔中的根標記

          html 標簽有三個特殊的屬性  

          • manifest 指定網頁緩存文件,可以讓用戶離線的時候也可以訪問文件。
          • xmlns 設置html名空間,比如把網頁設置成xhml的時候可以使用這個值。
          • lang 設置網頁的描述語言,比如中文是zh;英文是en。

          3、<head></head>頭部標簽在網頁中只能有一個,設置HTML文檔的頭部信息,里面內容不會在頁面中顯示出來·。

          head里面的標記

          • <meta> 標記
          • <title>定義網頁的標題
          • <link> 鏈接
          • <script> 標記JavaScript腳本的內容
          • <style> 標記css樣式
          • meta 標記

          4、<body></body>只能有一個,顯示網頁的主體內容。

          (一)、<meta>標簽

          <meta>元素的屬性:

          • name 描述信息的名稱,來標記這是一個什么樣的信息
          • http-equiv 描述行為
          • content 描述的內容
          • charset 指定網頁的編碼

          1、name 屬性

          1 <meta name="author" content="nyw">
          2     <!--作者, 定義網頁的作者 -->
          3 <meta name="description" content="meta標記學習">
          4     <!-- 描述,描述網頁的實際內容 -->
          5 <meta name="keywords" content="HTML,meta">
          6     <!-- 關鍵字,定義網頁關鍵字 -->

          2、http-equiv屬性

          1 <meta http-equiv="refresh" content="30">
          2     <!-- 網頁30s后自動刷新 -->
          3 <meta http-equiv="refresh" content="5,url=dom.html">
          4     <!-- 網頁30秒后跳轉到dom.html文檔 -->

          <meta http-equiv="refresh" content="5,url=dom.html">

          http-equiv描述網頁的行為,行為 refresh刷新,內容為5,表示5秒后跳轉到 dom.html這個文檔。

          3、content 屬性

          特殊屬性

          • content-type 指定http頭部信息的文字編碼(最為常用)
          • default-style 指定優先使用的樣式單(stylesheet)
          • refresh 用于網頁的自動刷新或是頁面跳轉
          • set-cookie 設置頁面的cookie(現在已經不再推薦使用)

          4、charset屬性

          指定網頁的編碼,推薦使用UTF-8來增加網頁的兼容性。

          代碼實例:

          為搜索引擎抓取機器人準備一些信息

          這段代碼可以禁止搜索引擎緩存和跟蹤網頁。

          <meta name="robots" content="noindex,nofollow">
              <!-- name定義的是機器人,內容部分表示不要被搜索引擎緩存,也不要被搜索引擎跟蹤 -->

          代碼實例:

           1 <!DOCTYPE html>
           2 <html lang="en">
           3 <head>
           4     <meta charset="UTF-8">
           5     <title>網頁標題(顯示在瀏覽器上)</title>
           6     <meta name="author" content="nyw">
           7     <!--作者, 定義網頁的作者 -->
           8     <meta name="description" content="meta標記學習">
           9     <!-- 描述,描述網頁的實際內容 -->
          10     <meta name="keywords" content="HTML,meta">
          11     <!-- 關鍵字,定義網頁關鍵字 -->
          12     <meta http-equiv="refresh" content="30">
          13     <!-- 網頁30s后自動刷新 -->
          14     <meta http-equiv="refresh" content="5,url=dom.html">
          15     <!-- 網頁30秒后跳轉到dom.html文檔 -->
          16     <meta name="robots" content="noindex,nofollow">
          17     <!-- name定義的是機器人,內容部分表示不要被搜索引擎緩存,也不要被搜索引擎跟蹤 -->
          18 </head>
          19 <body>
          20 </body>
          21 </html>

          (二)、title、base標記

          title和base標記都是寫在head標簽中

          title:設置網頁的標題

          寫法:<title>內容</title>。

          base:指定網頁跳轉基準URL,如果不指定的話默認為當前網站的當前路徑。

          寫法:<base href="http://www.aaa.zzz/">

          base屬性值:

          • href 指定網頁跳轉到基準URL,如果不指定的話則默認為當前網站的當前路徑。

          <base href="http://baidu.com/"> 這是將頁面跳轉到百度的網站打開。

          • target 指定鏈接的跳轉幀如果不指定的話,則是在當前頁面中跳轉。

          <base target="_blank"> 網頁中的鏈接都應該在新的窗口中打開。

          terget屬性值:

          • _blank 在新窗口中打開被鏈接的文檔
          • _self 默認值,在相同框架中打開被鏈接的文檔
          • _parent 在父框架集中
          • _top 在整個窗口中打開被鏈接文檔·
          • framename 在指定框架中打開被鏈接文檔

          (三)、link標記

          link標記:鏈接外部文件時使用的標記,可以把外部文件的內容引入到當前文件中來,使當前網頁實現更多的功能。

          link屬性:

          href:指定鏈接外部路徑的路徑和文件名,要設置全路徑并且帶文件名

          rel:引用文件,引用資源的類型定義

          我們在使用link標簽引用外部文件的時候,外部文件的類型是多種多樣的。

          alternate 代替文檔(種子,其他語言版本,其他格式等等)

          author 網頁的作者

          help 幫助文件的鏈接

          icon 網頁的圖標

          next 如果是連續網頁的時候,指定下一個網頁

          prefetch 把鏈接外部資源時提前緩存起來。

          prev 如果是連續網頁

          media 鏈接文件或是資源屬于哪一種資源。

          hreflang 鏈接文件的語言種類

          type 鏈接文件的mi/me類型(比如說,圖片圖標文本)

          sizes 根據link鏈接文件的類型,來指定文件的大小

          代碼示例:

          鏈接網頁圖標:

          網站的圖標指定,可以顯示在瀏覽器的圖標欄,也可以被手機讀取作為網站的圖標存入收藏夾
          1 <!-- 網站的圖標指定,可以顯示在瀏覽器的圖標欄,也可以被手機讀取作為網站的圖標存入收藏夾 -->
          2     <link rel="icon">
          3     <!-- 示例 -->
          4     <link rel="icon" href="img/favicon.png" type="image/png">
          5     <link rel="shortcut icon" href="img/favicon.ico" type="image/x-icon">
          6     <link rel="apple-touch-icon" href="img/apple-touch-icon.png" type="image/png">

          注意:后面的href和前面type標注的類型要一致,這樣既可以顯示在瀏覽器,又可以顯示在手機上

          鏈接外部樣式單

          1 <link rel="stylesheet">
          2     <link rel="stylesheet" href="style1.css" media="screen">
          3     <link rel="stylesheet" href="style2.css" title="主題樣式文件">
          4     <link rel=" alternate stylesheet" href="style3.css" title="可選樣式單">

          說明:

          alternate 會在瀏覽器中會彈出一個對話框,供用戶可以進行選擇

          media 表示媒體類型為屏幕,可以是手機,但不包括打印機和投影儀

          title 對這個link進行簡單的說明

          網站RSS種子指定

          <!-- 網站RSS種子指定 -->
              <link rel="alternate" type="application/rss+xml">

          為搜索引擎的準備的網頁的URL

          <!-- 為搜索引擎的準備的網頁的URL -->
              <link rel="canonical">
              <link rel="canonical" href="http://www.aaa.zzz/help.html">

          告訴搜索引擎代替URL是哪里。


          主站蜘蛛池模板: 亚洲片一区二区三区| 亚洲AV日韩精品一区二区三区| 亚洲国产美女福利直播秀一区二区| 亚洲熟妇无码一区二区三区 | 国产产一区二区三区久久毛片国语| 国产精品亚洲不卡一区二区三区 | 无码一区二区三区老色鬼| 日韩电影在线观看第一区| 国产精品99精品一区二区三区| 亚洲熟妇av一区| 亚洲一区二区三区深夜天堂| 精品一区二区三区四区| 国模吧无码一区二区三区| 久久久国产一区二区三区| 国产一区三区三区| 久久精品一区二区国产| 国产亚洲一区二区精品| 久久国产免费一区| 少妇精品无码一区二区三区| 国产一区二区内射最近更新| 国产亚洲一区二区三区在线观看| 国产成人一区二区三区视频免费| 国产一区视频在线| 亚洲av成人一区二区三区| 亚洲一区二区三区高清不卡 | 无码播放一区二区三区| 日本一区二区三区不卡视频| 四虎成人精品一区二区免费网站| 夜精品a一区二区三区| 日本精品夜色视频一区二区| 一区二区三区国模大胆| 亚洲一区爱区精品无码| 亚洲日本精品一区二区| 一区二区三区高清| 国产一区二区三区在线免费观看| 爆乳熟妇一区二区三区霸乳 | 亚洲乱码国产一区网址| 2014AV天堂无码一区| 亚洲一区无码中文字幕乱码| 黑巨人与欧美精品一区| 精品国产亚洲一区二区在线观看|