HarmonyOS4+NEXT—第三章 ArkUI基础与容器组件

264 阅读4分钟

鸿蒙开发系列合集

1、HarmonyOS4+NEXT—第一章 初识HarmonyOS4
2、HarmonyOS4+NEXT—第二章 安装真机模拟器
3、HarmonyOS4+NEXT—第三章 ArkUI基础与容器组件

3.1 ArkUI简介

        ArkUI(方舟UI框架)为应用的UI开发提供了完整的基础设施,包括简洁的UI语法、丰富的UI功能(组件、布局、动画以及交互事件),以及实时界面预览工具等,可以支持开发者进行可视化界面开发。

        ArkUI官方文档:developer.huawei.com/consumer/cn…

        ArkUI里面包含了很多种组件类型,其中最常用的一个是基础组件,它充当着页面元素的角色;另一个是容器组件,因为任何一个页面都离不开布局样式。

3.2 ArkUI基础组件

3.2.1 Image组件

    Image组件文档:developer.huawei.com/consumer/cn…

image.png

    1、声明Image组件并设置图片源

        Image组件里定义了3种图片源模式,分别是:网络图片、像素图、本地图片。其中我们最常用的是网络图片和本地图片。

        (1)src网络图片

Image('https://res.vmallres.com/pimages//uomcdn/CN/pms/202309/gbom/6942103109546/800_800_D8C79AD546E4A12920F05B427036ED8Bmp.png')

image.png

            加载网络图片,如果在PC端开发是没有问题的,但现在是开发手机应用,手机请求网络是需要手机系统设备许可的,因此它需要先去申请网络访问权限。

            关于权限设置,可以参考HarmonyOS4+NEXT—第二章 安装真机模拟器

        (2)本地图片

            对比网络图片而言,加载本地图片更加方便,它既不需要设置访问权限,也避免了外部原因的干扰,是比较推荐使用的方式。

            它有两种语法分别是$r和$rawfile,这两种方式加载应用内部的目录是不一样的。

            1.$r

                $r读取的是resources/base/media这个目录下的资源,使用的方法是$r('app.media.资源名'),这是固定的格式。

                注意:这里是不需要带上文件后缀名的,例如这里加载startIcon.png,只需要写成app.media.startIcon即可,不要写成startIcon.png。

image.png

            2.$rawfile

                $rawfile读取的是resources/rawfile目录下的资源,使用的方法是$rawfile('资源名.后缀名')。它跟$r的区别是$rawfile直接写文件即可,不过它需要带上文件后缀名。

image.png

    2、图片属性

        图片的属性也是非常的多,既有通用属性也有自带属性,这里介绍width属性。

        使用width指定宽度的时候,可以使用字符串格式,例如width('100%');也可以使用数字格式,例如width(250)。字符串格式比较好理解,而数字格式的需要说明一下,比如250并不是指250px,它有一个默认的单位叫vp虚拟像素,它不是屏幕像素,它会根据屏幕像素密度进行换算,确保同一个元素在不同设备上的视觉大小是统一的。

3.2.2 Text组件

    Text组件文档:developer.huawei.com/consumer/cn…

image.png

    1、限定词目录

        限定词其实就是设备信息,例如设备所属的国家、系统语言、型号等等,把这些信息拿过来拼在一起作为目录名就是限定词目录。这里的en_US和zh_CN使用的是语言和国家,en_US就是英语英国,zh_CN就是中文中国。

        我们在使用$r读取本地资源的时候,它会优先根据当前设备的信息,找到与之匹配的限定词目录去寻找资源,如果找不到才会去找base目录。Text读的文本内容其实读的是element目录下的string.json定义好的文本,app是固定前缀,string指的是string.json。这样我们可以根据不同的语言设置不同的文本。

        注意:如果在限定词目录下定义了变量,那么一定要在base目录也定义相同的变量,否则会报错。

image.png

        只在限定词目录下定义而没有在base目录下定义,它会弹出提示"该变量在默认配置没有找到"。

    2、切换语言

        在编辑器预览区里提供了一个切换语言的功能,便于我们测试在不同语言情况下的显示情况。

image.png

image.png

3.2.3 TextInput组件

    TextInput组件文档:developer.huawei.com/consumer/cn…

image.png

    这个TextInput组件其实就是我们常用UI组件里的Input输入框组件,不过一般UI库的Input组件只提供password类型,而TextInput还提供了Email、Number等其它类型,对于常用类型不需要我们去校验。

    1、声明TextInput

TextInput({placeholder: '请输入图片宽度', text: '123'})

image.png

    2、设置TextInput属性方法

TextInput({placeholder: '请输入图片宽度', text: '123'})
  .width(150)
  .backgroundColor('#ccc')
  .type(InputType.Password)
  .onChange(value => {
    console.log(value)
  })

image.png

        注意:这里绑定onChange方法之后,如果在声明组件的时候传入了text属性,它第一次加载的时候会立即触发onChange方法。

3.2.4 Button组件

    Button组件文档:developer.huawei.com/consumer/cn…

image.png

    Button组件的使用比较简单,没有太多需要注意的点,只需要参考上述案例使用即可。

3.2.5 Slider组件

    Slider组件文档:developer.huawei.com/consumer/cn…

image.png

3.3 ArkUI容器组件

    在ArkUI里,最常用的容器组件当属Row与Column,顾名思义就是行和列的布局。熟悉前端的很容易会联想到它其实就是CSS3的flex布局。

image.png

    主轴代表容器元素的排列方式,主轴与交叉轴共同影响着元素的对齐方式。

    1、justifyContent:子元素在主轴的对齐方式

image.png

    2、alignItems:子元素在交叉轴的对齐方式

image.png

        注意:在设置justifyContent主轴对齐方式的时候,Row和Column用的都是FlexAlign的属性。而在设置alignItem交叉轴对齐方式的时候,两者是不同的,Row用的是VerticalAlign,而Column用的是HorizontalAlign。

        其实这也比较好理解,对于Row行布局而言,交叉轴对它来说就是纵向对齐方式,所以它用VerticalAlign(vertical是垂直的意思);同理,Column的交叉轴就是横向对齐方式,所以它用HorizontalAlign(Horizontal是水平的意思)

3.4 ArkUI实现简单布局

image.png

    这里做一个简单的案例,熟悉一下基础组件和容器组件在实战的使用。

    1、基础组件的使用

        这个案例中涉及到Image、Text、TextInput、Button和Slider这5个基础组件,我们先不考虑容器组件,把这些基础组件放上去看看整体效果。

@Entry
@Component
struct Index {
  build() {
    Column() {
      Image($r('app.media.startIcon')).width(150)

      Text($r('app.string.width_label'))
        .fontSize(20)
        .fontWeight(FontWeight.Bold)

      TextInput({placeholder: '请输入图片宽度'})
        .width(150)
        .backgroundColor('#ccc')
        .type(InputType.Number)

      Button('缩小')
        .width(80)
        .fontSize(20)

      Button('放大')
        .width(80)
        .fontSize(20)

      Slider({
        min: 100,
        max: 300,
        value: 150,
        step: 10
      })
        .width('90%')
        .blockColor('#36D')
        .trackThickness(7)
        .showTips(true)
    }
    .width('100%')
  }
}

image.png

    2、运用容器组件

        (1)Image组件布局

            目前这个图片是没有固定的高度,它的缩放直接影响其它元素的位置。我们可以给Image组件外部包裹一个Row组件,给它设置一个高度。

Column() {
  Row() {
    Image($r('app.media.startIcon')).width(150)
  }.height(400)
  ......
}

            这样无论图片是放大还是缩小,它的占位是固定的,不会影响其它元素的位置了。

image.png

image.png

        (2)Text与TextInput组件布局

            这两个组件应该是在同一行显示的,那就给它们俩套上Row组件,并且设置它的宽度、padding内边距以及对齐方式。

            注意:这个padding和margin的用法,其实跟css是完全一致的,只是它用了方法去调用,传一个对象进去,用left、right、top、bottom键值对的方式来使用。

Column() {
  Row() {
    Image($r('app.media.startIcon')).width(this.imageWidth)
  }
  .height(400)

  Row() {
    Text($r('app.string.width_label'))
      .fontSize(20)
      .fontWeight(FontWeight.Bold)

    TextInput({placeholder: '请输入图片宽度', text: this.imageWidth.toString()})
      .width(150)
      .backgroundColor('#fff')
      .type(InputType.Number)
      .onChange(value => {
        this.imageWidth = parseInt(value)
      })
  }
  .width('100%')
  .padding({left: 14, right: 14})
  .justifyContent(FlexAlign.SpaceBetween)
}

image.png

        (3)Button组件布局

            同理,这两个按钮是同一行的,也是套一个Row组件,不过它们俩是在一行之中均分的位置,设置justifyContent属性为FlexAlign.SpaceEvenly即可。

Column() {
  Row() {
    Image($r('app.media.startIcon')).width(this.imageWidth)
  }
  .height(400)

  Row() {
    Text($r('app.string.width_label'))
      .fontSize(20)
      .fontWeight(FontWeight.Bold)

    TextInput({placeholder: '请输入图片宽度', text: this.imageWidth.toString()})
      .width(150)
      .backgroundColor('#fff')
      .type(InputType.Number)
      .onChange(value => {
        this.imageWidth = parseInt(value)
      })
  }
  .width('100%')
  .padding({left: 14, right: 14})
  .justifyContent(FlexAlign.SpaceBetween)

  Row() {
    Button('缩小')
      .width(80)
      .fontSize(20)
      .onClick(() => {
        if (this.imageWidth >= 10) {
          this.imageWidth -= 10
        }
      })

    Button('放大')
      .width(80)
      .fontSize(20)
      .onClick(() => {
        if (this.imageWidth <= 300) {
          this.imageWidth += 10
        }
      })
  }
  .width('100%')
  .justifyContent(FlexAlign.SpaceEvenly)
}  

image.png

        (4)样式优化

            这里每个Row组件之间没有间距,可以通过设置Column组件的Space进行设置,当然也可以使用我们比较属性的margin属性进行边距设置。例如在Button组的Row组件设置margin外边距:

Row() {
  Button('缩小')
    .width(80)
    .fontSize(20)
    .onClick(() => {
      if (this.imageWidth >= 10) {
        this.imageWidth -= 10
      }
    })

  Button('放大')
    .width(80)
    .fontSize(20)
    .onClick(() => {
      if (this.imageWidth <= 300) {
        this.imageWidth += 10
      }
    })
}
.width('100%')
.margin({top: 35, bottom: 35})
.justifyContent(FlexAlign.SpaceEvenly)

image.png