当前位置:网站首页>鸿蒙智能家居【1.0】

鸿蒙智能家居【1.0】

2022-07-07 16:59:00 InfoQ



应用场景:

  • 智能家居。
今天打造的这一款全新智能家庭控制系统,凸显应用在智能控制和用户体验的特点,开创国内智能家居系统体验新局面。新的系统主要应用在鸿蒙生态。
在开始之前大家可以先预览一下我完成之后的效果。

是不是很炫酷呢?

搭建OpenHarmony环境

完成本篇Codelab我们首先要完成开发环境的搭建,本示例以
DaYu200
开发板为例,参照以下步骤进行:
  • 获取OpenHarmony系统版本
    :标准系统解决方案(二进制)
  • 以3.0版本为例:

  • 搭建烧录环境
  • 完成DevEco Device Tool的安装
  • 完成Dayu200开发板的烧录
  • 搭建开发环境
  • 开始前请参考
    工具准备
     ,完成DevEco Studio的安装和开发环境配置。
  • 开发环境配置完成后,请参考
    使用工程向导
     创建工程(模板选择“Empty Ability”),选择eTS语言开发。
  • 工程创建完成后,选择使用
    真机进行调测
     。

相关概念

容器组件
  • Column
  • Row
  • Stack
基础组件
  • Text
  • TextInput
  • Button
  • Image
  • Navigation
通用
  • 边框设置
  • 尺寸设置
  • 点击控制
  • 布局约束
  • 背景设置
  • 点击事件
TS语法糖
好的接下来我将详细讲解如何制作

开发教学

创建好的 eTS工程目录

新建工程的ETS目录如下图所示。

各个文件夹和文件的作用:
  • index.ets
    :用于描述UI布局、样式、事件交互和页面逻辑。
  • app.ets
    :用于全局应用逻辑和应用生命周期管理。
  • pages
    :用于存放所有组件页面。
  • resources
    :用于存放资源配置文件。
接下来开始正文。
我们的主要操作都是在在pages目录中,然后我将用不到10分钟的时间,带大家实现这个功能。

拆解


根据设计图,我们可以分层展示,用Column包裹,大致分为这几步


可以看下本页的结构:


再详细一点:



import { SettingDetails } from './common/SettingDetails';
import router from '@ohos.router';

@Entry
@Component
struct Index {
  @State title: string = '智能家居体验'
  @State message: string = '你现在想要打开那些设置?'
  @State desc: string = '点击所有适用的选项。这将帮助我们\n自定义您的主页'
  @State Number: String[] = ['0', '1', '2', '3', '4']
  @State private isSelect: boolean = true;

  build() {

      Column() {
        Text(this.title)
         .fontSize(80)
         .fontWeight(FontWeight.Bold).onClick(() => {
          router.push({ url: 'pages/SensorScreen' })
       }).margin({ bottom: 60, top: 40 })
        Text(this.message)
         .fontSize(50)
         .fontWeight(FontWeight.Bold).onClick(() => {
          router.push({ url: 'pages/SensorScreen' })
       }).margin({ bottom: 60 })
        Text(this.desc)
         .fontSize(30)
         .textAlign(TextAlign.Center)
         .fontWeight(FontWeight.Bold)
         .onClick(() => {

         })
         .margin({ bottom: 60 })
        Row() {

          SettingDetails({
            image: "common/images/setting.png",
            title: "Maintenance\nRequests",
            isSelected: this.isSelect!
         })

          SettingDetails({ image: "common/images/grain.png", title: "Integrations\n", isSelected: this.isSelect! })

          SettingDetails({
            image: "common/images/ic_highlight.png",
            title: "Light\nControl",
            isSelected: this.isSelect!
         })

       }
        Row() {
          SettingDetails({ image: "common/images/opacity.png", title: "Leak\nDetector", isSelected: this.isSelect! })
          SettingDetails({
            image: "common/images/ac_unit.png",
            title: "Temperature\nControl",
            isSelected: this.isSelect!
         })
          SettingDetails({ image: "common/images/key.png", title: "Guest\nAccess", isSelected: this.isSelect! })


       }
        Button("NEXT")
         .fontSize(60)
         .fontColor(Color.Black)
         .width(600)
         .height(100)
         .backgroundColor(Color.Red)
         .margin({ top: 100 })
         .onClick(() => {
            router.push({ url: 'pages/SensorScreen' })
         })
     }
     .width('100%')
    
   .height('100%').backgroundColor("#F5F5F5")
 }
}

具体布局

具体布局设计到一些细节的地方,例如间隔,边框,当前组件尺寸设置等一些特殊情况,基本上就是嵌套,一层一层去实现。

代码结构


编码

Index.ets
import { SettingDetails } from './common/SettingDetails';
import router from '@ohos.router';

@Entry
@Component
struct Index {
  @State title: string = '智能家居体验'
  @State message: string = '你现在想要打开那些设置?'
  @State desc: string = '点击所有适用的选项。这将帮助我们\n自定义您的主页'
  @State Number: String[] = ['0', '1', '2', '3', '4']
  @State private isSelect: boolean = true;

  build() {

      Column() {
        Text(this.title)
         .fontSize(80)
         .fontWeight(FontWeight.Bold).onClick(() => {
          router.push({ url: 'pages/SensorScreen' })
       }).margin({ bottom: 60, top: 40 })
        Text(this.message)
         .fontSize(50)
         .fontWeight(FontWeight.Bold).onClick(() => {
          router.push({ url: 'pages/SensorScreen' })
       }).margin({ bottom: 60 })
        Text(this.desc)
         .fontSize(30)
         .textAlign(TextAlign.Center)
         .fontWeight(FontWeight.Bold)
         .onClick(() => {

         })
         .margin({ bottom: 60 })
        Row() {

          SettingDetails({
            image: "common/images/setting.png",
            title: "Maintenance\nRequests",
            isSelected: this.isSelect!
         })

          SettingDetails({ image: "common/images/grain.png", title: "Integrations\n", isSelected: this.isSelect! })

          SettingDetails({
            image: "common/images/ic_highlight.png",
            title: "Light\nControl",
            isSelected: this.isSelect!
         })

       }
        Row() {
          SettingDetails({ image: "common/images/opacity.png", title: "Leak\nDetector", isSelected: this.isSelect! })
          SettingDetails({
            image: "common/images/ac_unit.png",
            title: "Temperature\nControl",
            isSelected: this.isSelect!
         })
          SettingDetails({ image: "common/images/key.png", title: "Guest\nAccess", isSelected: this.isSelect! })


       }
        Button("NEXT")
         .fontSize(60)
         .fontColor(Color.Black)
         .width(600)
         .height(100)
         .backgroundColor(Color.Red)
         .margin({ top: 100 })
         .onClick(() => {
            router.push({ url: 'pages/SensorScreen' })
         })
     }
     .width('100%')

   .height('100%').backgroundColor("#F5F5F5")
 }
}


针对这一页:首先是头部


代码如下:
 Row() {

       Image($r("app.media.logo"))
         .objectFit(ImageFit.Contain)
         .width(200)
         .height(200)
         .borderRadius(21)

       Column() {
         Text('June 14, 2022')
           .fontSize(40).opacity(0.4)
           .fontWeight(FontWeight.Bold)
         Text('Good Morning,\nJianGuo',)
           .fontSize(60)
           .fontWeight(FontWeight.Bold)
       }


     }

其次是个人信息,包括头像等信息:



代码如下:

接下来就是温度和湿度

代码如下:
ow({ space: 120 }) {
        Column() {
          Text('40°',)
           .fontSize(40).opacity(0.4)
           .fontWeight(FontWeight.Bold)
          Text('TEMPERATURE',)
           .fontSize(40).opacity(0.4)
       }.margin({ left: 60 })

        Column() {
          Text('59%',)
           .fontSize(40).opacity(0.4)
           .fontWeight(FontWeight.Bold)
          Text('HUMIDITY',)
           .fontSize(40).opacity(0.4)
       }.margin({ right: 60 })
     }.margin({ top: 20 })



SensorScreen.ets
import { HomeDetails } from './common/homedetails';
// second.ets
import router from '@ohos.router';

@Entry
@Component
struct Second {
  @State message: string = 'Hi there'
  @State private isSelect: boolean = true;

  build() {

    Column() {
      Row() {

        Image($r("app.media.back"))
         .objectFit(ImageFit.Contain)
         .width(80)
         .height(80)
         .onClick(() => {
            router.back()
         })

        Blank()

        Text('Home')
         .fontSize(45)
         .fontWeight(FontWeight.Bold)


        Blank()
        Image($r("app.media.notifications_none"))
         .objectFit(ImageFit.Contain)
         .width(80)
         .height(80)
         .onClick(() => {
            router.back()
         })

     }

     .width('100%')

      Row() {

        Image($r("app.media.logo"))
         .objectFit(ImageFit.Contain)
         .width(200)
         .height(200)
         .borderRadius(21)

        Column() {
          Text('June 14, 2022')
           .fontSize(40).opacity(0.4)
           .fontWeight(FontWeight.Bold)
          Text('Good Morning,\nJianGuo',)
           .fontSize(60)
           .fontWeight(FontWeight.Bold)
       }


     }

      Row({ space: 120 }) {
        Column() {
          Text('40°',)
           .fontSize(40).opacity(0.4)
           .fontWeight(FontWeight.Bold)
          Text('TEMPERATURE',)
           .fontSize(40).opacity(0.4)
       }.margin({ left: 60 })

        Column() {
          Text('59%',)
           .fontSize(40).opacity(0.4)
           .fontWeight(FontWeight.Bold)
          Text('HUMIDITY',)
           .fontSize(40).opacity(0.4)
       }.margin({ right: 60 })
     }.margin({ top: 20 })


      Row() {
        HomeDetails({})

        HomeDetails({ image: "common/images/lightbull.png", isSelected: this.isSelect! })

     }

      Row() {


        HomeDetails({ image: "common/images/opacity.png" })
        HomeDetails({ image: "common/images/yytem0.png" })


     }

      Row(){
       Column(){
         Text('ADD',)
           .fontSize(40).opacity(0.4)
           .fontWeight(FontWeight.Bold)
         Text('NEW CONTROL',)
           .fontSize(40).opacity(0.4)
       }
       Blank()

       Image($r("app.media.add"))
         .objectFit(ImageFit.Contain)
         .width(100)
         .height(100)
         .borderRadius(21).margin({right:40})

     }.border({
        color:Color.White,
        width:8,
        radius:20
     }).width("88%").height(150)

   }.width("100%")
   .height('100%').backgroundColor("#F5F5F5")
 }
}


我们可以对,下面的这块进行封装

代码如下
@Entry
@Component
export struct SettingDetails {
  @State  private image: string = "common/images/setting.png"
  @State  private title: string = "Maintenance\nRequests"
  @State private isSelected: boolean = true;

  build() {


  Column() {
    Image(this.image)
     .objectFit(ImageFit.Contain)
     .width(140)
     .height(120)
     .margin(20)
     .border({
        width: 12, color: this.isSelected ? Color.White : Color.Red,
        radius: 20
     })
     .onClick(() => {
        this.isSelected = !this.isSelected;
     })
    Text(this.title).fontSize(32).width(200).textAlign(TextAlign.Center)
 }
}}
我们可以对,下面的这块进行封装


代码如下
@Entry
@Component
export struct SettingDetails {
  @State  private image: string = "common/images/setting.png"
  @State  private title: string = "Maintenance\nRequests"
  @State private isSelected: boolean = true;

  build() {


  Column() {
    Image(this.image)
     .objectFit(ImageFit.Contain)
     .width(140)
     .height(120)
     .margin(20)
     .border({
        width: 12, color: this.isSelected ? Color.White : Color.Red,
        radius: 20
     })
     .onClick(() => {
        this.isSelected = !this.isSelected;
     })
    Text(this.title).fontSize(32).width(200).textAlign(TextAlign.Center)
 }
}}

最后就是底部

代码如下:
 Row(){
 Column(){
 Text('ADD',)
 .fontSize(40).opacity(0.4)
 .fontWeight(FontWeight.Bold)
 Text('NEW CONTROL',)
 .fontSize(40).opacity(0.4)
 }
 Blank()

 Image($r("app.media.add"))
 .objectFit(ImageFit.Contain)
 .width(100)
 .height(100)
 .borderRadius(21).margin({right:40})

 }.border({
 color:Color.White,
 width:8,
 radius:20
 }).width("88%").height(150)

恭喜你

在本文中,通过实现智联汽车App示例,我主要为大家讲解了如下ArkUI(基于TS扩展的类Web开发范式)组件,以及路由跳转。
容器组件
  • Column
  • Row
  • Stack
基础组件
  • Text
  • Button
  • Image
  • Navigation
通用
  • 边框设置
  • 尺寸设置
  • 点击控制
  • 布局约束
  • 背景设置
  • 点击事件
TS语法糖
希望通过本教程,各位开发者可以对以上基础组件具有更深刻的认识。
后面的计划:
  • 智能互联
  • 硬件交互
  • 动画交互
原网站

版权声明
本文为[InfoQ]所创,转载请带上原文链接,感谢
https://xie.infoq.cn/article/fb20e40a8183b132ca85cb2ba