#过年不停更#HarmonyOS-ETS之紧急拨号 原创 精华

发布于 2022-2-16 10:08
浏览
2收藏

春节不停更,此文正在参加「星光计划-春节更帖活动」
作者:陈龙佳

前言

一直在学习关于鸿蒙官方文档,主要是学习基于JS扩展的类web开发范式,而随着开发文档的不断更新,SDK也更新到了8,随着TS的不断广泛应用,于是我就接触了基于TS扩展的类web开发范式,也就是ArkUI。本文主要是基于ArkUI实现的一个小项目,也可以说是一个demo,主要是通过ETS的语法完成一些关于界面相关的、简单的数据通信以及交互。

效果展示

#过年不停更#HarmonyOS-ETS之紧急拨号-开源基础软件社区

创建项目

首先打开devEco Studio编辑器,左上角找到File–>New–>New project,然后来到下面这个页面,对于第一次使用该编辑器时最令人的头疼的应该就是sdk的问题,首先ETS项目必须需要SDK7以上才可以使用,所以如果有创建失败的童鞋们请检查你们的SDK版本是否正确。

#过年不停更#HarmonyOS-ETS之紧急拨号-开源基础软件社区

项目架构

目录 描述
src 项目的源码主文件夹
components 公共组件的存放文件夹
Model 主要数据源的存放文件夹
pages 项目页面文件夹
app.ets 项目的入口文件
resources 应用的资源文件夹(字符串、图片、音频等)
config.json 应用配置文件

数据模型构建

1.定义一个接口来约束urgentDialList

// 这里使用TS中的interface来约束接口
interface UrgentDialList {
  id: number,
  EmergencyNumber: number,
  type: string
}

const urgentDialList: UrgentDialList[] = [
  {
    id: 1,
    EmergencyNumber: 110,
    type: "匪警"
  },
  {
    id: 2,
    EmergencyNumber: 120,
    type: "医疗救急"
  },
  {
    id: 3,
    EmergencyNumber: 119,
    type: "火警"
  }
]

2.构建initializeOnStartup方法来对页面数据进行初始化处理

export function initializeOnStartup(): Array<UrgentListData> {
  let urgentDialListArray: Array<UrgentListData> = []
  urgentDialList.forEach(item => {
    urgentDialListArray.push(new UrgentListData(item.id, item.EmergencyNumber, item.type))
  })
  return urgentDialListArray
}

主要涉及到的状态变量装饰器

装饰器 描述
@State 组件拥有的状态属性。每当@State装饰的变量更改时,组件会重新渲染更新UI
@Link 组件依赖于其父组件拥有的某些状态属性。每当任何一个组件中的数据更新时,另一个组件的状态都会更新,父子组件都会进行重新渲染。
@Prop 工作原理类似@Link,只是子组件所做的更改不会同步到父组件上,属于单向传递。

在这里我想说的是关于@Link跟@Prop都可以进行组件数据的传递,但是通过@Prop修饰的变量,父组件不能进行数据的修改,因为这样会破坏数据的单向性,而@Link是双向数据绑定的,可以进行数据的重新渲染以及修改。

主要涉及功能点

  • 打开弹框获取地理位置
  • 紧急拨号页面的跳转
  • 拨号键盘的呼入与呼出
  • 手势事件滑动呼叫紧急号码

主要工具函数类

1.showToast函数

作用:主要用来展示弹框,这里需要引入鸿蒙里一个包(import prompt from ‘@system.prompt’;)

async function showToast(message: string,duration:number = 5000) {
  await prompt.showToast({
    message,
    duration
  })
}

2.routerPage函数

作用:主要用来进行页面跳转,这里需要引入鸿蒙里一个包(import routerfrom ‘@system.router’;)

async function routerPage(path) {
  let option = {
    uri: `pages/${path}`
  }
  try {
    await router.push(option)
  } catch (err) {
    console.log(`fail callback, code: ${err.code}, msg: ${err.msg}`)
  }
}

组件封装

keyword组件

键盘组件主要使用Grid宫格布局,对于这种类似键盘或者九宫格的布局推荐使用grid布局,
采用网格容器,二维布局,将容器划分成"行"和"列",产生单元格,然后指定"项目所在"的单元格,可以任意组合不同的网格,做出各种各样的布局。
但是要注意一点,Text组件只能用来展示字符串,因此如果是想展示数字的话得需要通过toString()转换一下,这是我之前遇到的一个小问题。

@Component
export default struct Keyword {
  @State keySign: (string | number)[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, "*", 0, "#"]
  @State key: number | string= ""
  @Link inputNumber: string

  build() {
    Column({ space: 5 }) {
      Grid() {
        ForEach(this.keySign, key => {
          GridItem() {
            Text(key.toString())
              .fontSize(52)
              .fontColor("#fff")
              .fontWeight(500)
              .width('100%')
              .height('100%')
              .textAlign(TextAlign.Center)
              .onClick(() => {
                console.log(key);
                this.key = this.inputNumber
              })
          }
        })
      }
       // 这里使用到了grid中的columnsTemplate以及rowsTemplate属性,他会对元素进行区域分割
      .columnsTemplate('1fr 1fr 1fr')
      .rowsTemplate('1fr 1fr 1fr 1fr')
      .columnsGap(10)
      .rowsGap(10)
      .width('90%')
      .height(360)
    }
  }
}

urgentList组件

该组件主要用来渲染紧急拨号列表,在ArkUI中,主要使用forEach来遍历数据,进行页面展示。

import urgentListItem from "./urgentListItem.ets"
import {UrgentListData} from "../Model/urgentListData.ets"
import {initializeOnStartup} from "../Model/urgentListModel.ets"

@Component
export default struct UrgentList {
  private urgentItems: UrgentListData[]= initializeOnStartup()

  build() {
    List() {
      ForEach(this.urgentItems, item => {
        ListItem() {
          urgentListItem({ urgentItems: item })
        }
      }, item => item.id.toString())
    }
    .width("90%")
  }
}

urgentListItem组件

该组件中使用了手势事件,通过PanGesture()中的onActionEnd、onActionStart、onActionUpdate三个方法来对手势所触发的距离进行控制,当this.offsetX大于某一临界值时,滑动改变菜单布局或内容布局的left偏移量,手势抬起完成偏移量进行视图的更新。

1.首先,会使用到手势事件,通过判断手势滑动的偏移量offsetX来控制滑动后颜色改变

gesture():gesture: GestureType,mask?: GestureMask

鸿蒙系统提供如下Gesture类型:

LongPressGesture 长按手势
PanGesture 平移手势
PinchGesture 捏合手势
RotationGesture 旋转手势

2.响应手势事件

  • 组件通过gesture方法绑定手势对象,可以通过手势对象提供的事件相应响应手势操作。如通过TapGesture对象的onAction事件响应点击事件。
//手势事件
      .gesture(
      PanGesture()
        .onActionStart((event: GestureEvent) => {
          console.info('Pan start')
        })
        .onActionUpdate((event: GestureEvent) => {
          //          console.log(typeof `${this.offsetX}`);
        })
        .onActionEnd((event: GestureEvent) => {
          console.info('Pan end')
          this.offsetX = event.offsetX
          console.log(`${this.offsetX}`);
          if (Number(this.offsetX) > 60) {
            this.bgc = "#d94838"
            this.isSlide = true
             // 使用定时器来关闭滑动后的状态
            this.closeISettimeOut();
          }
        })
      )
  • 当响应事件结束后,关闭定时器来关闭滑动,重置效果。

    //关闭定时器 
      closeISettimeOut() {
        if (this.timer) {
          clearTimeout(this.timer)
        }
        this.timer = setTimeout(() => {
          this.isSlide = false;
          this.bgc = "rgba(255,255,255,0.30)"
        }, 2000)
      }
    

positionInfoDialog组件

功能点:询问是否自动获取地理位置,若继续,则显示当前地理位置,若取消则关闭弹框,显示初始值

@Component
export default struct PositionInfoDialog {
 //  这里的@Link主要用来组件之间传递数据
  @Link isShowDialog: boolean
  @Link userPosition: string

  build() {
    Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center }) {
      Column() {
        Text("自动获取位置信息服务")
          .height(100)
          .fontSize(28)
          .fontWeight(500)
          .width("100%")
      }

      Column() {
        Text("为帮助您更好地发起求助,进入紧急呼叫时,系统将自动获取您的位置信息,并显示在洁面顶部。点击位置信息可跳转至第三方地图应用。")
          .fontSize(16)
          .lineHeight(28)
          .letterSpacing(2)
          .margin({ bottom: 10 })
          .fontColor("rgba(0,0,0,0.90)")
        Text("本服务需联网并调用您的位置权限。在紧急呼叫状态中,相关权限将维持打开状态。是否继续?")
          .fontSize(16)
          .lineHeight(28)
          .letterSpacing(2)
          .fontColor("rgba(0,0,0,0.90)")
      }.height(220)

      Row() {
        Button('取消', { type: ButtonType.Normal, stateEffect: true })
          .width(150)
          .backgroundColor("#fff")
          .fontColor("#0a59f7")
          .fontSize(30)
          .onClick(() => {
            this.isShowDialog = false
          })

        Button('继续', { type: ButtonType.Normal, stateEffect: true })
          .width(150)
          .backgroundColor("#fff")
          .fontColor("#0a59f7")
          .fontSize(30)
          .onClick(() => {
            if (this.userPosition) {
              this.userPosition="广东省深圳市"
              this.isShowDialog = false
            }
          })
      }
    }
    .padding({ left: 14, right: 14, bottom: 20 })
    .margin({ bottom: 40 })
    .width("96%")
    .height(360)
    .backgroundColor("#fff")
    .borderRadius(24)
  }
}

总结

本文只是大致的使用ArkUI对页面进行了简单的布局以及事件的交互,没有涉及到太复杂的逻辑功能业务。
鸿蒙的路还很长,青春正好,故事还没有结束,而我们正走在探索的路上。如果想更多的了解以及深入学习鸿蒙生态的知识,可以参阅:ArkUI

项目源码

https://gitee.com/chen_longjia/ark-ui-emergency

更多原创内容请关注:中软国际 HarmonyOS 技术团队

入门到精通、技巧到案例,系统化分享HarmonyOS开发技术,欢迎投稿和订阅,让我们一起携手前行共建鸿蒙生态。

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
已于2022-2-16 10:53:52修改
5
收藏 2
回复
举报
回复
添加资源
添加资源将有机会获得更多曝光,你也可以直接关联已上传资源 去关联
    相关推荐