应用场景:
智能家居。
今天打造的这一款全新智能家庭控制系统,凸显应用在智能控制和用户体验的特点,开创国内智能家居系统体验新局面。新的系统主要应用在鸿蒙生态。
在开始之前大家可以先预览一下我完成之后的效果。
智能家居中控
是不是很炫酷呢?
搭建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语法糖
希望通过本教程,各位开发者可以对以上基础组件具有更深刻的认识。
后面的计划:
智能互联
硬件交互
动画交互