OpenHarmony应用开发之二维码生成器
鸿蒙智联汽车【1.0】
作者:坚果 公众号:"大前端之旅" 华为云享专家,InfoQ签约作者,OpenHarmony布道师,CSDN博客专家,电子发烧友鸿蒙MVP,阿里云专家博主,51CTO博客首席体验官,开源项目GVA成员之一,专注于大前端技术的分享,包括Flutter,小程序,安卓,VUE,JavaScript。
应用场景:
- 智能家居。
今天打造的这一款全新智能家庭控制系统,凸显应用在智能控制和用户体验的特点,开创国内智能家居系统体验新局面。新的系统主要应用在鸿蒙生态。
在开始之前大家可以先预览一下我完成之后的效果。
是不是很炫酷呢?
搭建OpenHarmony环境
完成本篇Codelab我们首先要完成开发环境的搭建,本示例以DaYu200开发板为例,参照以下步骤进行:
- 获取OpenHarmony系统版本:标准系统解决方案(二进制) 以3.0版本为例:
img
- 搭建烧录环境
- 完成DevEco Device Tool的安装
- 完成Dayu200开发板的烧录
- 搭建开发环境
- 开始前请参考工具准备 ,完成DevEco Studio的安装和开发环境配置。
- 开发环境配置完成后,请参考使用工程向导 创建工程(模板选择“Empty Ability”),选择eTS语言开发。
- 工程创建完成后,选择使用真机进行调测 。
相关概念
容器组件
- Column
- Row
- Stack
基础组件
- Text
- Button
- Image
- Navigation
通用
- 边框设置
- 尺寸设置
- 点击控制
- 布局约束
- 背景设置
- 点击事件
TS语法糖
好的接下来我将详细讲解如何制作
开发教学
创建好的 eTS工程目录
新建工程的ETS目录如下图所示。
img
各个文件夹和文件的作用:
- index.ets:用于描述UI布局、样式、事件交互和页面逻辑。
- app.ets:用于全局应用逻辑和应用生命周期管理。
- pages:用于存放所有组件页面。
- resources:用于存放资源配置文件。
接下来开始正文。
我们的主要操作都是在在pages目录中,然后我将用不到10分钟的时间,带大家实现这个功能。
拆解
image-20220706230542588
根据设计图,我们可以分层展示,用Column包裹,大致分为这几步
image-20220706231016908
可以看下本页的结构:
image-20220706232242915
再详细一点:
image-20220706232343167
代码语言:javascript复制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: "MaintenancenRequests",
isSelected: this.isSelect!
})
SettingDetails({ image: "common/images/grain.png", title: "Integrationsn", isSelected: this.isSelect! })
SettingDetails({
image: "common/images/ic_highlight.png",
title: "LightnControl",
isSelected: this.isSelect!
})
}
Row() {
SettingDetails({ image: "common/images/opacity.png", title: "LeaknDetector", isSelected: this.isSelect! })
SettingDetails({
image: "common/images/ac_unit.png",
title: "TemperaturenControl",
isSelected: this.isSelect!
})
SettingDetails({ image: "common/images/key.png", title: "GuestnAccess", 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")
}
}
具体布局
具体布局设计到一些细节的地方,例如间隔,边框,当前组件尺寸设置等一些特殊情况,基本上就是嵌套,一层一层去实现。
代码结构
image-20220706231113785
编码
Index.ets
代码语言:javascript复制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: "MaintenancenRequests",
isSelected: this.isSelect!
})
SettingDetails({ image: "common/images/grain.png", title: "Integrationsn", isSelected: this.isSelect! })
SettingDetails({
image: "common/images/ic_highlight.png",
title: "LightnControl",
isSelected: this.isSelect!
})
}
Row() {
SettingDetails({ image: "common/images/opacity.png", title: "LeaknDetector", isSelected: this.isSelect! })
SettingDetails({
image: "common/images/ac_unit.png",
title: "TemperaturenControl",
isSelected: this.isSelect!
})
SettingDetails({ image: "common/images/key.png", title: "GuestnAccess", 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")
}
}
image-20220706230620896
针对这一页:首先是头部
image-20220706232459401
代码如下:
代码语言:javascript复制 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)
}
}
其次是个人信息,包括头像等信息:
image-20220706232621793
代码如下:
代码语言:javascript复制
接下来就是温度和湿度
image-20220706232715798
代码如下:
代码语言:javascript复制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
代码语言:javascript复制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")
}
}
我们可以对,下面的这块进行封装
image-20220706231310224
代码如下
代码语言:javascript复制@Entry
@Component
export struct SettingDetails {
@State private image: string = "common/images/setting.png"
@State private title: string = "MaintenancenRequests"
@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)
}
}}
我们可以对,下面的这块进行封装
image-20220706231425068
image-20220706232810459
代码如下
代码语言:javascript复制@Entry
@Component
export struct SettingDetails {
@State private image: string = "common/images/setting.png"
@State private title: string = "MaintenancenRequests"
@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)
}
}}
最后就是底部
image-20220706232904753
代码如下:
代码语言:javascript复制 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语法糖
希望通过本教程,各位开发者可以对以上基础组件具有更深刻的认识。
后面的计划:
- 智能互联
- 硬件交互
- 动画交互