[文章]HarmonyOS入门教程—学习如何完成Page内和Page间的页面导航跳转

阅读量0
0
2
1. 概述      在HarmonyOS里,Ability是应用所具备能力的抽象,一个应用可以具备多种能力(即可以包含多个Ability),HarmonyOS支持应用以Ability为单位进行部署。其中Page Ability可以用于提供与用户交互的能力,一个Page可以由一个或多个AbilitySlice构成,AbilitySlice是指应用的单个页面及其控制逻辑的总和。
  • 在一个Ability里,我们可以使用present()/presentForResult() 方法从一个AbilitySlice导航到一个新的AbilitySlice,即Page内不同AbilitySlice的跳转,如图1-1;
  • 我们也可以在AbilitySlice里面使用startAbility()/startAbilityForResult() 方法来启动一个新的Ability,如图1-2。

图1-1 通过present()/presentForResult() 方法实现AbilitySlice间导航
图1-2 构造Operation对象,通过startAbility()/startAbilityForResult()实现不同Page间导航

在本Codelab中,我们尝试构建2个Ability、3个AbilitySlice来完成两种类型的跳转。
参考上面的图,我们在MainAbilitySlice页面,写两个简单的按钮,一个让它实现Page内跳转,另一个让它实现Page间跳转;在NewAbilitySlice和SecondAbilitySlice页面,通过一个按钮来让它回到第一个页面,实际完成图如下。
图1-3 点击第一个按钮跳转到第二个AbilitySlice,然后跳回

图1-4 点击第二个按钮跳转到第二个Ability,然后跳回

   

2. 任务一:新建项目      
在此任务中,您学会如何新建一个项目,并进行相关的设置。
开发准备
  • 开始前请参考下载与安装软件、配置开发环境,完成DevEco Studio的安装和开发环境配置。
  • 开发环境配置完成后,请参考创建和运行Hello World创建工程,以使用Java语言开发、设备类型为 "Phone"的"Application"为例,模板选择"Empty Feature Ability(Java)"。
  • 工程创建完成后,使用Phone模拟器运行该工程。

   

3. 任务二:编写页面布局      
在这个任务中,我们需要完成多个页面的新建和设计。在Java UI框架中,系统提供了两种编写布局的方式:在XML中声明UI布局和在代码中创建布局,我们以XML的方式为例。

在完成任务一后,我们可以看到系统自动创建了MainAbility和MainAbilitySlice。在"Project"窗口,点击"entry > src > main > resources > base > layout",打开"ability_main.xml"文件。


我们编写一个文本和两个按钮,使用DependentLayout布局,通过Text和Button组件来实现, "ability_main.xml"的示例代码如下:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <DirectionalLayout
  3.      xmlns:ohos="http://schemas.huawei.com/res/ohos"
  4.      ohos:height="match_parent"
  5.      ohos:width="match_parent"
  6.      ohos:alignment="center"
  7.      ohos:orientation="vertical">

  8.      <Text
  9.          ohos:id="$+id:main_text"
  10.          ohos:text="嗨,我是 MainAbilitySlice,看标题就知道我在哪个Page啦"
  11.          ohos:width="320fp"
  12.          ohos:height="match_content"
  13.          ohos:text_alignment="center"
  14.          ohos:multiple_lines="true"
  15.          ohos:text_size="20fp"
  16.          ohos:above="$+id:enter_second"
  17.          ohos:bottom_margin="50vp"/>

  18.      <Button
  19.          ohos:id="$+id:enter_newAbilitySlice"
  20.          ohos:width="260vp"
  21.          ohos:height="45vp"
  22.          ohos:text="导航到 NewAbilitySlice"
  23.          ohos:multiple_lines="true"
  24.          ohos:text_size="20fp"
  25.          ohos:bottom_margin="20vp"
  26.          ohos:center_in_parent="true"
  27.          ohos:background_element="$graphic:background_ability_main"/>

  28.      <Button
  29.          ohos:id="$+id:enter_second"
  30.          ohos:width="260vp"
  31.          ohos:height="45vp"
  32.          ohos:text="导航到 SecondAbility"
  33.          ohos:multiple_lines="true"
  34.          ohos:text_size="20fp"
  35.          ohos:bottom_margin="20vp"
  36.          ohos:center_in_parent="true"
  37.          ohos:background_element="$graphic:background_ability_main"/>

  38. </DirectionalLayout>
复制代码

代码中的按钮使用了background_element="$graphic: background_ability_main " ,即"entry > src > main > resources > base > graphic"中的"background_ability_main.xml"文件,示例代码为:

  1. <shape xmlns:ohos="http://schemas.huawei.com/res/ohos"
  2.         ohos:shape="rectangle">
  3.      <corners
  4.              ohos:radius="10"/>
  5.      <solid
  6.              ohos:color="#ffc0c0c0"/>
  7.      <stroke
  8.              ohos:color="#ff00ff7f"
  9.              ohos:width="0.4vp"/>
  10. </shape>
复制代码

完成上述步骤后,页面布局如下图所示:

然后我们来创建第二个Page,在"Project"窗口,打开"entry > src > main > java > 包名",右键点击"slice"文件夹,选择"New > Ability > Empty Page Ability(Java)",命名为"SecondAbility",单击回车键,系统会创建"SecondAbility.java"和"slice/SecondAbilitySlice.java"。

在"Project"窗口,点击"entry > src > main > resources > base > layout",打开"ability_second.xml"文件,增加信息显示区域和跳转按钮,示例代码如下。

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <DirectionalLayout
  3.     xmlns:ohos="http://schemas.huawei.com/res/ohos"
  4.     ohos:height="match_parent"
  5.     ohos:width="match_parent"
  6.     ohos:alignment="center"
  7.     ohos:orientation="vertical">

  8.     <Text
  9.         ohos:id="$+id:second_text"
  10.         ohos:width="320fp"
  11.         ohos:height="match_content"
  12.         ohos:multiple_lines="true"
  13.         ohos:text="嗨, 我是 SecondAbilitySlice"
  14.         ohos:text_alignment="center"
  15.         ohos:text_size="20fp"
  16.         ohos:above="$+id:second_back_first"
  17.         ohos:bottom_margin="50vp"/>

  18.     <Button
  19.         ohos:id="$+id:second_back_first"
  20.         ohos:width="260vp"
  21.         ohos:height="45vp"
  22.         ohos:text="回到MainAbility"
  23.         ohos:multiple_lines="true"
  24.         ohos:text_size="20fp"
  25.         ohos:bottom_margin="20vp"
  26.         ohos:center_in_parent="true"
  27.         ohos:background_element="$graphic:background_ability_main"/>

  28. </DirectionalLayout>
复制代码

第二个页面布局完成了,如下图所示:

最后我们在"entry > src > main > java> 包名 >slice"文件夹上右键新建一个"NewAbilitySlice.java"文件,并在"entry > src > main > resources > base > layout"里新建"ability_main_new.xml"文件,用于实现Page之内跳转调用。
"ability_main_new.xml"文件中,同样增加一个信息显示区域和跳转按钮,示例代码为:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <DirectionalLayout
  3.     xmlns:ohos="http://schemas.huawei.com/res/ohos"
  4.     ohos:height="match_parent"
  5.     ohos:width="match_parent"
  6.     ohos:alignment="center"
  7.     ohos:orientation="vertical">

  8.     <Text
  9.         ohos:id="$+id:new_text"
  10.         ohos:width="320fp"
  11.         ohos:height="match_content"
  12.         ohos:multiple_lines="true"
  13.         ohos:text="我是 NewAbilitySlice。麻烦看看标题,请告诉我现在在哪个Page呢?"
  14.         ohos:text_alignment="center"
  15.         ohos:text_size="20fp"
  16.         ohos:above="$+id:second_back_first"
  17.         ohos:bottom_margin="50vp"/>

  18.     <Button
  19.         ohos:id="$+id:new_to_main"
  20.         ohos:width="260vp"
  21.         ohos:height="45vp"
  22.         ohos:text="回到MainAbilitySlice"
  23.         ohos:multiple_lines="true"
  24.         ohos:text_size="20fp"
  25.         ohos:bottom_margin="20vp"
  26.         ohos:center_in_parent="true"
  27.         ohos:background_element="$graphic:background_ability_main"/>

  28. </DirectionalLayout>
复制代码

完成上述代码后,页面布局如下图所示:

最后我们对Ability页面的标题栏进行修改,便于我们分辨页面。
在"Project"窗口,点击"entry > src > main ",打开"config.json"文件,修改"abilities"中两个"label"字段分别为"Page MainAbility""Page SecondAbility"。
默认情况下,label字段生成为引用模式不可直接修改,按住Ctrl鼠标左键点击该字段,就可以跳转到被引用的string.json文件,修改对应字段就可以了。

  1. {
  2.   "string": [
  3.     {
  4.       "name": "entry_MainAbility",
  5.       "value": "Page MainAbility"
  6.     },   
  7.     {
  8.       "name": "entry_SecondAbility",
  9.       "value": "Page SecondAbility"
  10.     },  

  11.     ...

  12.   ]
  13. }
复制代码

4. 任务三:编写AbilitySlice间的导航      
打开"entry > src > main > java> 包名 >slice"中的"MainAbilitySlice.java"文件,添加两个按钮的响应逻辑,实现点击按钮跳转到下一页。
其中,Page内AbilitySlice间的导航选择使用presentForResult()实现,可以获得从导航目标AbilitySlice返回时的返回结果;Page间的导航,我们在后文完成startEnterSecondAbility()方法后实现。

  1. private Text backValueText;
  2.   
  3. [url=home.php?mod=space&uid=2735960]@Override[/url]
  4. public void onStart(Intent intent) {
  5.      super.onStart(intent);
  6.      super.setUIContent(ResourceTable.Layout_ability_main);

  7.      //start entering the NewAbilitySlice
  8.      Component enterNewAbilitySliceButton = findComponentById(ResourceTable.Id_enter_newAbilitySlice);
  9.      enterNewAbilitySliceButton.setClickedListener(listener -> presentForResult(new NewAbilitySlice() , new Intent(), 0));

  10.      //start entering the SecondAbility page
  11.      Component enterSecondAbilityButton = findComponentById(ResourceTable.Id_enter_second);
  12.      enterSecondAbilityButton.setClickedListener(component -> startEnterSecondAbility());

  13.      backValueText = (Text) findComponentById(ResourceTable.Id_main_text);
  14. }
复制代码

打开同文件夹下新建的"NewAbilitySlice.Java"文件,通过setResult()完成返回结果的实现。具体参考代码如下:
  1. package com.huawei.abilityintent.slice;

  2. import com.huawei.abilityintent.ResourceTable;
  3. import ohos.aafwk.ability.AbilitySlice;
  4. import ohos.aafwk.content.Intent;
  5. import ohos.agp.components.Component;

  6. public class NewAbilitySlice extends AbilitySlice {
  7.      @Override
  8.      public void onStart(Intent intent) {
  9.          super.onStart(intent);
  10.          super.setUIContent(ResourceTable.Layout_ability_main_new);

  11.          Component newToMainButton = findComponentById(ResourceTable.Id_new_to_main);
  12.          newToMainButton.setClickedListener(component -> terminate());
  13.      }

  14.      @Override
  15.      public void onActive() {
  16.          super.onActive();

  17.          Intent intent = new Intent();
  18.          intent.setParam("key", "我从NewAbilitySlice跳回来咯");
  19.          setResult(intent);
  20.      }

  21.      @Override
  22.      public void onForeground(Intent intent) {
  23.          super.onForeground(intent);
  24.      }
  25. }
复制代码

然后我们继续在"MainAbilitySlice.java"中补充下面代码,通过onResult完成返回结果的接收,并显示在页面的Text控件中。
  1. /**
  2.   * Result of presentForResult()
  3.   */
  4. @Override
  5. protected void onResult(int requestCode, Intent resultIntent) {
  6.      if (requestCode != 0 || resultIntent == null) {
  7.          return;
  8.      }
  9.      String result = resultIntent.getStringParam("key");
  10.      backValueText.setText(result);
  11. }
复制代码

这样,Page内的两个AbilitySlice的导航跳转就完成了。

5. 任务四:编写Page之间的导航      
在"entry > src > main > java> 包名 "中"MainAbility.java"文件中,我们可以看到在onStart()中已经通过路由导航到MainAbilitySlice页面。

  1. public class MainAbility extends Ability {
  2.     @Override
  3.     public void onStart(Intent intent) {
  4.         super.onStart(intent);
  5.         super.setMainRoute(MainAbilitySlice.class.getName());
  6.     }
  7. }
复制代码

同理"SecondAbility.java"也已经导航到"SecondAbilitySlice.java"页面,接下来我们来完成两个Page Ability之间的导航。

打开 "entry > src > main > java> 包名 >slice"中的"MainAbilitySlice.java"文件,我们进一步完成Page间导航按钮的响应逻辑,实现对应的方法startEnterSecondAbility()。

Page间的导航可以使用startAbility()或startAbilityForResult()方法,获得返回结果的回调为onAbilityResult()。为了获取返回值,我们这里使用startAbilityForResult()方法跳转到SecondAbility。
示例代码如下:
  1. /**
  2.   * Explicit Startup
  3.   */
  4. private void startEnterSecondAbility() {
  5.      Intent intent = new Intent();
  6.      Operation operation = new Intent.OperationBuilder().withDeviceId("")
  7.              .withBundleName(getBundleName())
  8.              .withAbilityName("com.huawei.abilityintent.SecondAbility")
  9.              .build();
  10.      intent.setOperation(operation);
  11.      intent.setParam("key", "我从MainAbility进到了SecondAbility");
  12.      startAbilityForResult(intent, 1);
  13. }
复制代码

在同目录下的"SecondAbilitySlice.java"文件中,我们对从MainAbility中获取到的信息通过Text控件进行展示,并且通过按钮点击事件完成terminnate()操作。

  1. @Override
  2. public void onStart(Intent intent) {
  3.      super.onStart(intent);
  4.      super.setUIContent(ResourceTable.Layout_ability_second);
  5.       
  6.      Component secondBackFirstButton = findComponentById(ResourceTable.Id_second_back_first);
  7.      secondBackFirstButton.setClickedListener(component -> terminate());

  8.      Text showParametersText = (Text) findComponentById(ResourceTable.Id_second_text);
  9.      showParametersText.setText(intent.getStringParam("key"));
  10. }
复制代码

同时,我们在SecondAbility页面中设置返回MainAbility需要的数据。在"SecondAbility.java"中,我们调用setResult()设置返回结果:

  1. @Override
  2. protected void onActive() {
  3.      super.onActive();
  4.      Intent intent = new Intent();
  5.      intent.setParam("key", "我从SecondAbility跳回来啦");
  6.      setResult(0, intent);
  7. }
复制代码

说明
如果是在AbilitySlice中,我们也可以通过下面方式完成setResult()设置返回结果哟~
getAbility().setResult(0, intent);

最后,在"MainAbilitySlice.java"中增加下面代码,完成返回结果的回调函数onAbilityResult(),将返回结果显示在页面上:
  1. @Override
  2. protected void onAbilityResult(int requestCode, int resultCode, Intent resultData) {
  3.      if (resultCode != 0 || resultData == null) {
  4.          return;
  5.      }
  6.      String result = resultData.getStringParam("key");
  7.      backValueText.setText(result);
  8. }
复制代码

6. 相关概念与参考      
开发指南API 参考   
7. 总结      
Page内可以使用present()或presentForResult()实现导航,使用presentForResult()时可以获得从导航目标AbilitySlice返回时的返回结果。
  • 返回结果由导航目标AbilitySlice在其生命周期内通过setResult()进行设置。
  • 当用户从导航目标AbilitySlice返回时,系统将回调onResult()来接收和处理返回结果,您需要重写该方法。
Page间的导航可以使用startAbility()或startAbilityForResult()方法,使用startAbilityForResult()方法时可以获得导航目标Ability返回时的返回结果。
  • 在导航目标Ability中调用setResult()来设置返回结果。
  • 获得返回结果的回调为onAbilityResult()。
   

8. 编码挑战      
本节提供了一个简单的家庭作业,用来测试您的学习情况。

目标

构建两个Page,各使用一个TextField框实现在两个页面间传递对话,如:
-"早上好,今天天气真不错。"
-"嗯呢!早上好,我正准备去华为体验店体验一下HarmonyOS,要一起去吗~"
   


回帖

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容图片侵权或者其他问题,请联系本站作侵删。 侵权投诉
链接复制成功,分享给好友