入门应用HelloWorld

当新建完毕一个鸿蒙项目之后,自带有HelloWorld的代码

  • 页面中的包含关系

如下图所示,MainAbility(界面)包含一个或多个MainAbilitySlice(子界面)
MainAbilitySlice(子界面)包含要显示的内容

在这里插入图片描述

MainAbility是项目启动的第一个界面,在界面里面不是直接显示内容的。在界面里面展示的是子界面,我们也称之为切片slice。在子界面里面才是显示内容的,这也正是为什么我们的逻辑代码都要写在slice文件中

  • 配置文件config.json

所有的模块,界面等信息,都会在这个文件中进行配置。鸿蒙启动之后,先解析这个文件,这个文件分为三类app deviceConfig module

{
  "app": {//整个项目的配置,包含了厂商信息,版本号等
    "bundleName": "com.example.myapplicationnewtest",//包名
    "vendor": "example",//是应用开发厂商的描述,也就是开发公司的名字
    "version": {
      "code": 1000000,//用户看到的版本号
      "name": "1.0.0"//用户看不到的,只能公司内部人员使用的版本号
    }
  },
  "deviceConfig": {},//表示应用在设备删搞得配置信息,比如是否允许使用网络流量,是否支持设备未解锁状态直接启动等
  "module": {//表示整个代码的配置信息,比如程序在运行时候的所有界面,以及第一个要启动的界面是谁
    "package": "com.example.myapplicationnewtest",//包名
    "name": ".MyApplication",//hap包的名字
    "mainAbility": "com.example.myapplicationnewtest.MainAbility",//表示HAP包的入口名称
    "deviceType": [//表示项目可以在哪些设备上运行,因为可能有多个设备,所以有个方括号,表示这些值可以写到一个数组里
      "phone"
    ],
    "distro": {//表示HAP包的描述信息
      "deliveryWithInstall": true,//当前HAP包是否可以支持随应用安装,一般为true
      "moduleName": "entry",//当前HAP的名称
      "moduleType": "entry",//当前HAP的类型,有entry和feature
      "installationFree": false
    },
    "abilities": [//表示当前模块内的所有Ability
      {
        "skills": [//表示Ability能接受到的Intent的特征
          {
            "entities": [//表示能够接收的Intent的Ability的类别(视频,桌面应用)
              "entity.system.home"
            ],
            "actions": [//表示能够接收的Intent的action值
              "action.system.home"
            ]
          }
        ],
        "orientation": "unspecified",
        "visible": true,
        "name": "com.example.myapplicationnewtest.MainAbility",
        "icon": "$media:icon",//表示Ability图标资源文件的索引,表示引用media目录下的icon资源
        "description": "$string:mainability_description",
        "label": "$string:entry_MainAbility",//应用安装后用户设备显示的名称
        "type": "page",//可以为page service或data
        "launchType": "standard"//表示启动模式,支持standard和singleton
      }
    ]
  }
}
  • 程序的启动过程

当程序刚开始启动的时候,会解析config.json中的信息,获取到第一个要加载的界面,也就是mainAbility,通过包名 + 类名定位到要运行的类MainAbility,所以界面启动,在这个界面里面又加载了MainAbilitySlice切片,在该切片中展示的内容为Layout包中的ability_main。

在这里插入图片描述

页面跳转功能

在这里插入图片描述

把HelloWorld界面改为第一个界面,并且添加一个按钮
写第二个界面SecondAbility
书写跳转关系

界面布局。这两种方式创建出的布局没有本质差别,但是XML方式较为方便简单,以后开发中,尽量用XML布局的方式

  • 在XML中声明UL布局
<?xml version="1.0" encoding="utf-8"?>
<DependentLayout
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:width="match_parent"
ohos:height="match_parent"
ohos:background_element="#000000">

<Text
ohos:id="$+id:text"
ohos:width="match_content"
ohos:height="match_content"
ohos:text="Hello World"
ohos:text_color="white"
ohos:text_size="32fp"
ohos:center_in_parent="true"/>
<Button
ohos:id="$+id:button"
ohos:width="match_content"
ohos:height="match_content"
ohos:text="Next"
ohos:text_size="19fp"
ohos:text_color="white"
ohos:top_padding="8vp"
ohos:bottom_padding="8vp"
ohos:right_padding="80vp"
ohos:left_padding="80vp"
ohos:background_element="$graphic:background_button"
ohos:below="$id:text"
ohos:horizontal_center="true" />
</DependentLayout>

其中宽和高的取值分别可以是固定的数值,match_content以及match_parent
具体数值10表示以像素为单位,10vp表示以屏幕相对像素为单位。
content表示组件大小与它的内容占据大大小范围相适应
parent表示组件大小将扩展为父组件允许的最大值,它将占据父组件方向上的剩余大小

  • 在代码中创建布局
    需要在SecondAbilitySlice中分别创建组件和布局,并将他们进行组织关联。并且我们还需要设置页面布局大小和背景色,以及设置文本的布局,下面代码只是简单的一个介绍。
public class SecondAbilitySlice extends AbilitySlice {
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        //super.setUIContent(ResourceTable.Layout_ability_second);

        //1.创建布局对象
        DirectionalLayout dl = new DirectionalLayout(this);

        //2.创建文本对象
        Text t = new Text(this);
        //设置内容
        t.setText("第二个页面");
        //设置文字大小
        t.setTextSize(55);
        //设置文字颜色
        t.setTextColor(Color.BLUE);

        //3.把文本对象添加到布局当中
        dl.addComponent(t);

        //4.把布局添加到子界面当中
        super.setUIContent(dl);
    }

    @Override
    public void onActive() {
        super.onActive();
    }

    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }
}
  • 代码实现页面跳转
public class MainAbilitySlice extends AbilitySlice implements Component.ClickedListener {
    Button btu ;
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);

        //1.找到按钮 id
        btu = (Button) findComponentById(ResourceTable.Id_but1);

        //2.给按钮添加一个点击事件
        //如果没有添加点击事件,那么用鼠标点击按钮之后是没有任何反应的。
        //如果我们给按钮添加了点击事件,那么用鼠标点击按钮之后,就可以执行对应的代码
        //理解方式:
        //给btu这个按钮添加了点击事件
        //当我们用鼠标点击了btu这个按钮之后,就可以执行本类中onClick方法
        btu.setClickedListener(this);

    }

    @Override
    public void onActive() {
        super.onActive();
    }

    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }


    @Override
    public void onClick(Component component) {
        //点击按钮只要要执行的代码
        //跳转到第二个页面中
        if(component == btu){
            //只有点击了btu这个按钮之后,才进行跳转

            //跳转到哪个页面中(意图)
            Intent i = new Intent();
            //包含了要跳转的页面信息
            Operation operation = new Intent.OperationBuilder()
                    .withDeviceId("")//要跳转到哪个设备上,如果传递一个没有内容的字符串,表示跳转本机
                    .withBundleName("com.example.myapplication")//我要跳转到哪个应用上,小括号里面可以写报名
                    .withAbilityName("com.example.myapplication.SecondAbility")//要跳转的页面
                    .build();//表示将上面的三个信息进行打包
            //把打包之后的operation设置到意图当中
            i.setOperation(operation);
            //跳转页面
            startAbility(i);
        }
    }
}

最后运行结果如下两张图所示
在这里插入图片描述
在这里插入图片描述

编程方式创建简单页面布局

这几天一直遇到个问题,我们都知道项目启动的首页面是MainAbility并且会自动加载MainAbilitySlice。那么问题来了,假设我又创建了一个ExampleAbility(创建Ability的时候,DEV会自动帮我们生成对应的slice文件和graphic里面的xml文件和layout里面的xml文件)那么我如何把ExampleAbility设置成我的首页面呢?

无外乎,在请教高人之后,他们给出了两种方法。
第一种比较傻的方法是我们都知道MainAbility和ExampleAbility内容几乎完全一样,所以我们可以在MainAbility中设置setMainRoute的路由为ExampleAbilitySlice即可。如下图所示。

package com.example.myexampleapplication;

import com.example.myexampleapplication.slice.ExampleAbilitySlice;
import com.example.myexampleapplication.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);
        super.setMainRoute(ExampleAbilitySlice.class.getName());
    }
}

第二种方法我觉得很实用,我们需要修改config.json文件中的内容。主要是修改abilities中的文件

 "abilities": [
      {
        "orientation": "unspecified",
        "visible": true,
        "name": "com.example.myexampleapplication.MainAbility",
        "icon": "$media:icon",
        "description": "$string:mainability_description",
        "label": "$string:entry_MainAbility",
        "type": "page",
        "launchType": "standard"
      },
      {
        "skills": [
          {
            "entities": [
              "entity.system.home"
            ],
            "actions": [
              "action.system.home"
            ]
          }
        ],
        "orientation": "unspecified",
        "name": "com.example.myexampleapplication.ExampleAbility",
        "icon": "$media:icon",
        "description": "$string:exampleability_description",
        "label": "$string:entry_ExampleAbility",
        "type": "page",
        "launchType": "standard"
      }
    ]

我们需要哪个Ability作为首界面,我们就把skills的内容复制给它,如上图我想要ExampleAbility作为首界面,因此我就把skills的内容复制到对应的数组对象里。最后用编程方式创建的Ability如下图所示

在这里插入图片描述
其余页面并未做任何更改,因此我们只需要修改ExampleAbilitySlice页面

package com.example.myexampleapplication.slice;

import com.example.myexampleapplication.ResourceTable;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.Button;
import ohos.agp.components.Text;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.utils.Color;
import ohos.agp.utils.LayoutAlignment;

public class ExampleAbilitySlice extends AbilitySlice {
    //三个重写的方法均继承于AbilitySlice类,其又继承AbilityContext类,后者又继承Context接口
    //继承关系DirectionLayout继承ComponentContainer类,后者又继承Component类,Component类又继承JAVA的Object类
    @Override
    public void onStart(Intent intent) {
        //onStart和setUIContent都来自于AbilitySlice类
        super.onStart(intent);
        //super.setUIContent(ResourceTable.Layout_ability_example);
        //声明布局
        DirectionalLayout directionalLayout= new DirectionalLayout(getContext());
        //设置布局大小
        //setWidth和setHeight方法继承Component类 里面的参数继承ComponentContainer这个类。
        directionalLayout.setWidth(ComponentContainer.LayoutConfig.MATCH_PARENT);
        directionalLayout.setHeight(ComponentContainer.LayoutConfig.MATCH_PARENT);
        //设置布局属性
        //setOrientation来自本类,设置布局的方向 setPadding来自于Component设置布局间距。
        directionalLayout.setOrientation(Component.VERTICAL);
        directionalLayout.setPadding(32,32,32,32);

        //getContext来自于AbilityContext,为什么这个地方可以写getContext呢?首先我们查阅继承关系可知道,这个地方的构造函数传参应该为Context类型的参数
        //Text和DirectionLayout同理。而getContext是来自于AbilityContext这个类,然后这个类又继承Context接口,因此这个地方可以填getContext
        Text text=new Text(getContext());
        //setText和setTextSize都是来自Text类中的方法,很好理解
        text.setText("编码创建视图布局");
        text.setTextSize(80);
        //setId是来自于Component这个类的方法,需要额外注意。
        text.setId(100);
        //为组件添加对应布局的布局属性,设置文本的布局,调用DirectionLayout中的构造方法,这个构造方法可以传递两个参数,参数与上面一样。
        DirectionalLayout.LayoutConfig layoutConfig=new DirectionalLayout.LayoutConfig(ComponentContainer.LayoutConfig.MATCH_CONTENT, ComponentContainer.LayoutConfig.MATCH_CONTENT);
        //alignment来自DirectionLayout.LayoutConfig属性,LayoutAlignment是引入的类
        layoutConfig.alignment= LayoutAlignment.HORIZONTAL_CENTER;
        //setLayoutConfig来自于Component
        text.setLayoutConfig(layoutConfig);
        //将Text添加到布局中,addComponent来自于ComponentContainer
        directionalLayout.addComponent(text);
        //类似的还添加一个Button
        Button button=new Button(getContext());
        //setMargins来自于ComponentContainer,同上
        layoutConfig.setMargins(0,50,0,0);
        button.setLayoutConfig(layoutConfig);
        button.setText("更新信息");
        button.setTextSize(50);
        //设置页面背景色,shapeElement来自于引入类,构造方法可以不传参!
        ShapeElement background=new ShapeElement();
        //下面两个方法都来自于ShapeElement这个类,setRgbColor构造函数需要RgbColor类型的参数,于是只能new一个,来自于ohos.agp.colors.RgbColor;
        background.setRgbColor(new RgbColor(0,125,255));
        background.setCornerRadius(25);
        //前面两个来自于Component类
        button.setBackground(background);
        button.setPadding(10,10,10,10);
        //来自于Text类,为什么Button可以使用Text这个类中的方法呢?Button继承了Text类这个方法!注意看源代码!
        button.setTextColor(Color.WHITE);
        button.setClickedListener(new Component.ClickedListener() {//点击事件方法来自于Component
            @Override
            public void onClick(Component component) {
                System.out.println(this);
            }
        });
        //addComponent来自于ComponentContainer类
        directionalLayout.addComponent(button);
        //将布局作为根布局添加到视图树中
        super.setUIContent(directionalLayout);

    }

    @Override
    public void onActive() {
        super.onActive();
    }

    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }
}



Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐