鸿蒙界面跳转
概述
HarmonyOS应用开发中的Ability相当于一个容器,容器中可以存放多个AbilitySlice。一个Ability相当于一个page,一个AbilitySlice相当于page中的一个子页面,一个应用中可以有多个Ability。本文主要介绍的是同一个Ability中不同AbilitySlice之间的跳转,及不同Ability中的AbilitySlice之间的跳转。
准备
文中涉及到多个Ability和AbilitySlice,所以需要提前准备好,使用的时候创建也可以。
创建Ability
创建Ability继承Ability即可
public class SecondAbility extends Ability {
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setMainRoute(SecondAbilitySlice.class.getName());
...
}
}
项目中已经自动创建了MainAbility,再创建一个SecondAbility即可。
创建AbilitySlice
创建AbilitySlice需要继承AbilitySlice
public class MainAbilitySlice1 extends AbilitySlice {
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_main_1);
...
}
...
}
这里根据需要分别创建了MainAbilitySlice1,MainAbilitySlice2,SecondAbilitySlice,SecondAbilitySlice1。
添加路由
AbilitySlice创建完后需要在Ability中添加相对应的路由。
public class MainAbility extends Ability {
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setMainRoute(MainAbilitySlice.class.getName());
addActionRoute("main_slice1",MainAbilitySlice1.class.getName());
addActionRoute("main_slice2", MainAbilitySlice2.class.getName());
}
}
setMainRoute是设置Ability中的主页面,而addActionRoute则是添加其他页面。addActionRoute中第一个参数则是需要在config.json中先声明,然后在Ability中使用才会有效。
"abilities": [
{
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home",
"main_slice1",
"main_slice2"
]
}
],
"orientation": "unspecified",
"name": "com.harmonyos.pages.MainAbility",
"icon": "$media:icon",
"description": "$string:mainability_description",
"label": "$string:app_name",
"type": "page",
"launchType": "standard"
},
...
需要在skills中actions中添加。SecondAbility 也是如此。
分类
根据跳转类型的不同,可以大致分为三类:无参跳转、有参跳转、含返回参跳转。具体细分可以分为同一Ability中的不同AbilitySlice之间的无参、有参和含返回参跳转,不同Ability之间的无参、有参和含返回参跳转。
同一Ability中不同AbilitySlice之间的无参跳转
AbilitySlice跳转通常使用Intent。
Text mainPage = (Text) findComponentById(ResourceTable.Id_main_page_without_param);
mainPage.setClickedListener(component -> {
// 同page之间的无参跳转
Intent intent1 = new Intent();
present(new MainAbilitySlice1(),intent1);
});
发现组件并添加点击事件。
效果
同一Ability中不同AbilitySlice之间的带参跳转
添加信息
带参跳转,这里以携带简单的字符串为例,先将需要携带的信息添加进Intent中。
findComponentById(ResourceTable.Id_main_page_with_param).setClickedListener(component -> {
// 同page之间的带参跳转
Intent intent1 = new Intent();
intent1.setParam("param", "MainPage向MainPage2携带的参数");
present(new MainAbilitySlice2(), intent1);
});
接受信息
在MainAbilitySlice2中接收信息并解析。
Text mainPage2 = (Text) findComponentById(ResourceTable.Id_main_page2);
if(intent != null){
String param = intent.getStringParam("param");
mainPage2.setText(param);
}
效果
同一Ability中不同AbilitySlice之间的含返回参跳转
添加跳转数据
跳转出发页可以携带信息,也可以不携带信息,这里以携带信息为例
mainPageForResult = (Text) findComponentById(ResourceTable.Id_main_page_for_result);
mainPageForResult.setClickedListener(component -> {
// 同page之间的带返回参跳转
Intent intent1 = new Intent();
intent1.setParam("param","param");
presentForResult(new MainAbilitySlice1(),intent1,520);
});
和之前不同之处在与这里使用的是presentForResult,而不是present,同时还需要设置requestCode,这里设置为520。设置requestCode是为了区分信息来源,以免有多个信息的时候产生混淆。
添加返回数据
findComponentById(ResourceTable.Id_main_page1).setClickedListener(component -> {
// 带参返回
Intent intent2 = new Intent();
intent2.setParam("back","这是MainAbilitySlice1返回给MainAbilitySlice的数据");
setResult(intent2);
terminate();
});
terminate结束当前页面,setResult是页面结束的时候将信息返回。
接收返回的信息
@Override
protected void onResult(int requestCode, Intent resultIntent) {
super.onResult(requestCode, resultIntent);
if(requestCode == 520){
String result = resultIntent.getStringParam("back");
mainPageForResult.setText(result);
}
}
在接收返回信息的页面中重写onResult方法,对返回的信息进行解析。
效果
不同Ability中不同AbilitySlice之间的无参跳转
跳转
findComponentById(ResourceTable.Id_main_page_goto_other_page).setClickedListener(component -> {
// 不同page无参跳转
Intent intent1 = new Intent();
Operation builder = new Intent.OperationBuilder()
.withBundleName("com.harmonyos.pages")
.withAbilityName(".SecondAbility")
.withDeviceId("")
.build();
intent1.setOperation(builder);
startAbility(intent1);
});
和同一Ability不同的是这是使用的是startAbility,而不是present。builder使用的时候需要注意类型,withAbilityName中以"."开头是因为前面的名称和”com.harmonyos.pages“一致,所以可以省略。withBundleName里面需要填写的内容可以在config.json中找到,一般就是包名。withDeviceId中填写空字符,是因为填写空字符时程序可以自动获取当前设备id。
效果
不同Ability中不同AbilitySlice之间的带参跳转
跳转
findComponentById(ResourceTable.Id_main_page_goto_other_page_with_param).setClickedListener(component -> {
// 不同page带参跳转
Intent intent1 = new Intent();
intent1.setParam("param","MainPage向SecondPage携带的参数");
Operation builder = new Intent.OperationBuilder()
.withAbilityName(".SecondAbility")
.withBundleName("com.harmonyos.pages")
.withDeviceId("")
.build();
intent1.setOperation(builder);
startAbility(intent1);
});
携带的数据和之前的一样,添加到Intent中就行,Intent中添加的数据类型不止String类型,基本数据类型,数列化等数据都支持,可满足99%的需求。
效果
不同Ability中不同AbilitySlice之间的含返回参跳转
跳转前
mainPageGotoOtherPageForResult.setClickedListener(component -> {
// 不同page带返回参跳转
Intent intent1 = new Intent();
Operation builder = new Intent.OperationBuilder()
.withAbilityName(".SecondAbility")
.withBundleName("com.harmonyos.pages")
.withDeviceId("")
.build();
intent1.setOperation(builder);
startAbilityForResult(intent1,521);
});
在MainAbilitySlice中使用startAbilityForResult,并设置requestCode为521,然后跳转至SecondAbility。
跳转后
Text secondPage = (Text) findComponentById(ResourceTable.Id_second_page);
secondPage.setClickedListener(component -> {
Intent intent1 = new Intent();
intent1.setParam("result","result");
getAbility().setResult(520,intent1);
terminate();
});
在SecondAbility中设置返回数据为”result“,然后使用terminate方法结束SecondAbility,并设置resultCode为520。注意使用的是getAbility().setResult,而不是setResult,否则消息发送不成功。
接收返回参数
@Override
protected void onAbilityResult(int requestCode, int resultCode, Intent resultData) {
super.onAbilityResult(requestCode, resultCode, resultData);
if(requestCode == 521 && resultCode == 520){
String result = resultData.getStringParam("result");
// 可以对数据进行判空,防止空指针
mainPageGotoOtherPageForResult.setText(result);
}
}
重写onAbilityResult,然后匹配requestCode和resultCode,对返回数据进行解析。
效果
不同Ability中非主AbilitySlice之间的跳转
跳转前
Text mainPage2 = (Text) findComponentById(ResourceTable.Id_main_page2);
mainPage2.setClickedListener(component -> {
Intent intent1 = new Intent();
intent1.setAction("second_slice1");
startAbility(intent1);
});
这里的跳转是从MainAbilitySlice2跳转至SecondAbilitySlice1,两个页面都不是MainRoute,当然这里面也分带参,不带参和携带返回参,操作和前面一样,这里就不一一描述了。注意second_slice1需要提前在config.json中声明,否则该字符串无意义。
效果
总结
不同页面之间的跳转及数据传递基本上和Android中一样。
Ability和Android中的Activity差不多,AbilitySlice相当于Android中的Fragment,但是使用要比Fragment灵活多样。
对于Android开发者来讲,鸿蒙应用开发对其是天然友好。
注
由于没有鸿蒙的设备,所以效果图中使用的手机均为远程模拟器。