HarmonyOS ArkTS 本地库和三方库的用法

系统 OpenHarmony
本项目基于HarmonyOS的ArkUI框架TS扩展的声明式开发范式。

​想了解更多关于开源的内容,请访问:​

​51CTO 开源基础软件社区​

​https://ost.51cto.com​

项目介绍

项目内容: 自定义基础组件和容器组件、依赖库概念、本地依赖库的创建和引用、三方库的引用。

工具版本: DevEco Studio 3.1 Canary1。

SDK版本: 3.2.1.4(API Version 9 Canary1)(Stage模型)。

本项目基于​​HarmonyOS​​的ArkUI框架TS扩展的声明式开发范式,关于语法和概念直接看官网官方文档地址:​​基于TS扩展的声明式开发范式​​,

效果演示

HarmonyOS ArkTS 本地库&三方库的用法-开源基础软件社区

依赖库

实际项目中,我们会把 公共代码 或 独立功能(UI、算法…) 抽离出来封装成依赖库,提供调用方法,调用者只需将依赖库导入到项目中,使用简单的代码调用来完成开发,提高了开发效率。一般的依赖库特点:调用简单、扩展性高。

本地库

本地库主要是指未上架到npm中心,只是本地依赖使用的库。

1、本地库的创建

a.鼠标移到工程目录顶部,鼠标右击,选择New>Module。

HarmonyOS ArkTS 本地库&三方库的用法-开源基础软件社区

b.在Choose Your Ability Template界面中,选择Ohos Library,点击下一步。

HarmonyOS ArkTS 本地库&三方库的用法-开源基础软件社区

c.在Configure the New Module界面中,配置模块信息,点击完成。

  • Module name:新增模块的名称。
  • Language:选择开发HarmonyOS npm包的语言。
  • Device type:选择HarmonyOS npm包支持的设备类型。
  • Enable Native:是否创建一个用于调用C++代码的HarmonyOS npm共享模块。

HarmonyOS ArkTS 本地库&三方库的用法-开源基础软件社区

2、本地库的依赖

在Terminal窗口中,进入模块目录中,执行如下命令进行安装,并会在package.json中自动添加依赖。

npm install (本地模块的路径)

npm install ../library
  • 1.

HarmonyOS ArkTS 本地库&三方库的用法-开源基础软件社区

3、本地库的调用

在依赖库的根目录中,index.ets文件提供了对外的导出。

HarmonyOS ArkTS 本地库&三方库的用法-开源基础软件社区

在entry中index.ets页面中,引入依赖库。

// 导入本地依赖库
import { MainPage } from '@ohos/library'

@Entry
@Component
struct Index {
  build() {
    Column() {
      // 使用自定义组件
      MainPage()
    }.width('100%').height('100%')
    .justifyContent(FlexAlign.Center)
  }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.

自定义组件

可复用的 UI 单元,可组合其它组件,被 @Component 装饰的结构体。

本项目依赖库中自定义组件:公共标题栏、侧滑菜单容器。

1、标题栏组件

标题自定义,左右都可以定义图标和点击事件。且左边图标有默认事件:页面返回。

import router from '@ohos.router';
/**
 * 自定义标题栏
 */
@Component
export struct TitleBar {
  // 左边图标是否显示
  private isShowLeft = true
  // 左边图标
  private leftIcon = $r('app.media.back')
  // 左边点击事件,默认返回上一页
  private leftClickEvent = () => {
    router.back()
  }
  // 标题
  private title = '标题'
  // 右边图标是否显示
  private isShowRight = false
  // 右边图标
  private rightIcon = $r('app.media.icon')
  // 左边点击事件
  private rightClickEvent: () => void

  build() {
    Column() {
      Stack() {
        Text(this.title).fontSize(20).fontColor('#ff1a1a1a')
        Row() {
          if (this.isShowLeft) {
            Image(this.leftIcon).size({ width: 55, height: 55 }).padding(15)
              .onClick(() => this.leftClickEvent())
          }
          Blank()
          if (this.isShowRight) {
            Image(this.rightIcon).size({ width: 55, height: 55 }).padding(15)
              .onClick(this.rightClickEvent)
          }
        }.width('100%')
      }.width('100%').height(0).layoutWeight(1)

      Divider().color('#ffbababa')
    }.width('100%').height(55)
  }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.

标题栏组件的使用:

import { TitleBar } from '@ohos/library'
@Entry
@Component
struct Index {
  build() {
    Column() {
      TitleBar({ title: '主页', leftIcon: $r('app.media.menu'),
        leftClickEvent: () => {
          // 左图标点击事件
        }
      })
    }.width('100%').height('100%')
  }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.

2、侧滑菜单容器

左右滑动可以控制菜单,菜单打开时,背景透明度改变,使用动画效果打开或关闭菜单。

/**
 * 滑动菜单
 */
@Component
export struct SlideMenuContainer {
  // 菜单的宽度
  @State menuWidth: number = 0
  // 菜单x轴偏移量
  @State menuOffsetX: number = 0
  // 菜单偏移最小量
  private offsetXMin = 0
  // 菜单偏移最大量
  private offsetXMax = 0
  // 第一次按下的x坐标
  private firstDownX = -1
  // 上次按下的x坐标
  private lastDownX = -1
  // 背景透明度
  @State bgOpacity: number = 0
  // 滑动方向
  private slideDirection: 'left' | 'right'
  // 菜单布局
  @BuilderParam menu: any
  // 内容布局
  @BuilderParam content: any
  // 定时器ID
  private intervalID = 0
  // 是否打开菜单
  @Link @Watch('isOpenChanger') isOpen: boolean
  isOpenChanger() {
    if (this.isOpen) {
      this.openMenu()
    }
  }
  build() {
    Stack({ alignContent: Alignment.Start }) {
      // 内容布局
      Column() {
        this.content()
      }.width('100%').height('100%')

      if (this.bgOpacity) {
        // 透明背景
        Column() {
        }.width('100%').height('100%')
        .backgroundColor(Color.Black).opacity(this.bgOpacity)
      }
      // 菜单布局
      Column() {
        this.menu()
      }.width(this.menuWidth).height('100%')
      .backgroundColor(Color.White)
      .offset({ x: this.menuOffsetX })
    }.width('100%').height('100%')
    .onTouch((event) => this.onTouchEvent(event))
    .onAreaChange((oldValue: Area, newValue: Area) => {
      // 监听回调中获取容器的宽度
      const width = Number.parseInt(newValue.width.toString())
      this.menuWidth = width * 0.7
      this.menuOffsetX = -this.menuWidth
      this.offsetXMin = -this.menuWidth
      this.offsetXMax = 0
    })
  }
  /**
   * 触摸事件
   */
  onTouchEvent(event: TouchEvent) {
    const x = event.touches[0].x
    switch (event.type) {
      case TouchType.Down: // 手指按下
        {
          this.firstDownX = x
          this.lastDownX = x
          clearInterval(this.intervalID)
        }
        break;
      case TouchType.Move: // 手指移动
        {
          // 计算这次x坐标点与上次x坐标点的差
          const diff = x - this.lastDownX
          this.lastDownX = x
          // 累计算出滑动的距离
          this.menuOffsetX += diff
          // 确定方向
          this.slideDirection = diff > 0 ? 'right' : 'left'
          // 限定距离范围
          if (this.menuOffsetX >= this.offsetXMax) this.menuOffsetX = this.offsetXMax
          if (this.menuOffsetX <= this.offsetXMin) this.menuOffsetX = this.offsetXMin
          // 更改背景透明度
          this.bgOpacity = 0.6 * Math.abs(this.menuWidth + this.menuOffsetX) / this.menuWidth
        }
        break;
      case TouchType.Up: // 手指抬起
        {
          if (Math.abs(x - this.firstDownX) < 5) {
            return
          }
          if (this.slideDirection === 'left') {
            // 是否小于宽度的3/2
            const isClose = Math.abs(this.menuWidth + this.menuOffsetX) < this.menuWidth * 2 / 3
              isClose ? this.closeMenu() : this.openMenu()
          } else {
            // 是否大于宽度的3/1
            const isOpen = Math.abs(this.menuWidth + this.menuOffsetX) > this.menuWidth / 3
              isOpen ? this.openMenu() : this.closeMenu()
          }
        }
        break;
      default:
        break;
    }
  }
  /**
   * 定时器改变偏移量
   * @param type 偏移量 加或减
   */
  intervalChangeOffset(type: 1 | -1) {
    this.intervalID = setInterval(() => {
      this.menuOffsetX += type * 15
      if (this.menuOffsetX >= this.offsetXMax) {
        this.menuOffsetX = this.offsetXMax
        clearInterval(this.intervalID)
      }
      if (this.menuOffsetX <= this.offsetXMin) {
        this.menuOffsetX = this.offsetXMin
        clearInterval(this.intervalID)
        this.isOpen = false
      }
      this.bgOpacity = 0.6 * Math.abs(this.menuWidth + this.menuOffsetX) / this.menuWidth
    }, 5)
  }
  /**
   * 打开菜单
   */
  openMenu() {
    this.intervalChangeOffset(1)
  }
  /**
   * 关闭菜单
   */
  closeMenu() {
    this.intervalChangeOffset(-1)
  }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115.
  • 116.
  • 117.
  • 118.
  • 119.
  • 120.
  • 121.
  • 122.
  • 123.
  • 124.
  • 125.
  • 126.
  • 127.
  • 128.
  • 129.
  • 130.
  • 131.
  • 132.
  • 133.
  • 134.
  • 135.
  • 136.
  • 137.
  • 138.
  • 139.
  • 140.
  • 141.
  • 142.
  • 143.
  • 144.
  • 145.

侧滑菜单的使用 (部分代码)

import { SlideMenuContainer } from '@ohos/library'
@Entry
@Component
struct Index {
  @State isOpen: boolean = false
  ......
  /**
   * 内容布局
   */
  @Builder ContentLayout() {...}
  /**
   * 菜单布局
   */
  @Builder MenuLayout() {...}

  build() {
    Column() {
      SlideMenuContainer({
        isOpen: $isOpen,
        content: this.ContentLayout(),
        menu: this.MenuLayout()
      })
    }.width('100%').height('100%')
  }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.

三方库

其他公司开源的库或者个人开源的库,上架到npm中心供其他开发者下载使用的库。

本项目中使用的是三方库是:lottieETS 一个适用于OpenHarmony的动画库。

依赖方式和本地库一样,使用命令安装:

npm install @ohos/lottieETS --save
  • 1.

以下示例只是简单用法,其他方法的使用请查看官方的文档:​​lottieETS 使用说明​​。

// 导入三方库
import lottie from '@ohos/lottieETS'
@Entry
@Component
struct LottieDemo {
  private setting: RenderingContextSettings = new RenderingContextSettings(true)
  private crc: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.setting)
  private lottiePath = 'common/lottie/car-loading2-data.json'
  private lottieName = 'carName'
  @State isPlay: boolean = false
  build() {
    Column() {
      Canvas(this.crc)
        .width(300)
        .height(300)
        .margin({ top: 30, bottom: 50 })
        .margin({ top: 30, bottom: 50 })
        .onReady(() => {
          lottie.loadAnimation({
            container: this.crc, // 需要绑定Canvas的CanvasRenderingContext2D
            renderer: "canvas", // 目前只支持canvas模式
            loop: true, // 是否循环播放
            autoplay: false, // 是否自动播放
            name: this.lottieName, // 设置lottie动画名称
            path: this.lottiePath // 指定lottie动画资源路径
          })
        })
        .onDisAppear(() => {
          // Canvas销毁时顺带销毁lottie动画
          lottie.destroy(this.lottieName)
        })
      Button(this.isPlay ? '暂停' : '播放')
        .width(150).height(30)
        .backgroundColor('#2D9FE5')
        .onClick(() => {
          this.isPlay = !this.isPlay
          this.isPlay ? lottie.play(this.lottieName) : lottie.pause(this.lottieName)
        })
    }.width('100%').height('100%')
  }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.

结尾

此项目中本地库和三方库的依赖都比较简单,难点是自定义组件的使用,还是需要多看官方的文档。最后希望鸿蒙社区越来越多的人加入,创作出更多优秀三方库。

项目地址:https://gitee.com/liangdidi/CallLibraryDemo。

每天进步一点点、需要付出努力亿点点。

​想了解更多关于开源的内容,请访问:​

​51CTO 开源基础软件社区​

​https://ost.51cto.com​​。

责任编辑:jianghua 来源: 51CTO开源基础软件社区
相关推荐

2023-02-07 15:43:13

三方库适配鸿蒙

2023-03-22 09:09:21

鸿蒙Speexdsp

2019-07-30 11:35:54

AndroidRetrofit

2021-10-11 06:38:52

Go开源库语言

2021-01-27 10:04:46

鸿蒙HarmonyOS动画

2021-04-28 15:07:06

鸿蒙HarmonyOS应用

2020-10-29 09:56:23

Linux静态库动态库

2014-07-22 10:56:45

Android Stu第三方类库

2022-06-06 07:50:55

PythonJSON

2022-11-16 14:05:06

Tesseract应用调用

2021-03-18 16:07:08

鸿蒙HarmonyOS应用

2011-07-25 14:14:49

iPhone SQLITE Pldatabase

2013-01-15 13:50:22

iOS开发开源库

2024-05-16 08:14:19

Carbon​Format​格式化

2022-05-21 23:56:16

Python库搜索Python

2023-03-01 07:21:33

2010-03-03 15:10:49

第三方Python库

2013-08-14 09:50:32

iOS类库

2022-10-11 15:04:28

NAPI开发鸿蒙

2012-01-04 14:02:26

JsonCpp
点赞
收藏

51CTO技术栈公众号