利用场景:
- 智慧出行。
智能汽车是集环境感知、布局决策、多等级辅助驾驶等性能于一体的智能网联综合零碎,它集中使用了计算机、古代传感、信息交融、通信、人工智能及自动控制等技术,是典型的高新技术综合体。简略的说,智能汽车的呈现将逐渐放松车、手、眼,让开车,用车变得简略。这样的产品对有本儿不敢上路的人来说或者是大大的福音。
在南方冬天有点冷,这个时候,去车里,温度很低,给人一种不难受的感觉,那么有没有一种可能,就是能够通过手机 App,实现对车内的一些状况的监测,答案是有的,明天做的这个 App,就是这样一个 App。
我要实现的性能次要有
- 用户能够解锁任何车门,
- 查看电池状态,
- 管制空调温度,
- 查看轮胎的气压。
在开始之前大家能够先预览一下我实现之后的成果。如下图所示:
是不是很炫酷呢?
搭建 OpenHarmony 环境
实现本篇 Codelab 咱们首先要实现开发环境的搭建,本示例以 DaYu200 开发板为例,参照以下步骤进行:
-
获取 OpenHarmony 零碎版本:规范零碎解决方案(二进制)
以 3.0 版本为例:
-
搭建烧录环境
- 实现 DevEco Device Tool 的装置
- 实现 Dayu200 开发板的烧录
-
搭建开发环境
- 开始前请参考工具筹备,实现 DevEco Studio 的装置和开发环境配置。
- 开发环境配置实现后,请参考应用工程向导 创立工程(模板抉择“Empty Ability”),抉择 eTS 语言开发。
- 工程创立实现后,抉择应用真机进行调测。
相干概念
容器组件
- Column
- Row
- Stack
根底组件
- Text
- Button
- Image
- Navigation
通用
- 边框设置
- 尺寸设置
- 点击管制
- 布局束缚
- 背景设置
- 点击事件
TS 语法糖
好的接下来我将具体解说如何制作
开发教学
创立好的 eTS 工程目录
新建工程的 ETS 目录如下图所示。
各个文件夹和文件的作用:
- index.ets:用于形容 UI 布局、款式、事件交互和页面逻辑。
- app.ets:用于全局应用逻辑和利用生命周期治理。
- pages:用于寄存所有组件页面。
- resources:用于寄存资源配置文件。
接下来开始注释。
咱们的次要操作都是在在 pages 目录中,而后我将用不到 10 分钟的工夫,带大家实现这个性能。
拆解
依据设计图,咱们能够分为内容展示区和菜单。
针对这一点,咱们能够用 Navigation 组件作为 Page 页面的根容器,通过属性设置来展现页面的题目、工具栏、菜单。
Navigation() {Column({ space: 20}) {if (this.index == 0)
DoorLook()
else if (this.index == 1)
Battery()
else if (this.index == 2)
Temp()
else if (this.index == 3)
Tyre()}
.backgroundColor(Color.Black)
.justifyContent(FlexAlign.SpaceAround)
.alignItems(HorizontalAlign.Center)
.justifyContent(FlexAlign.Center)
.size({width: '100%', height: '100%'})
} .size({width: '100%', height: '100%'})
.toolBar(this.toolbarWidget())
.hideToolBar(this.hideToolBar)
.hideTitleBar(this.hideTitleBar)
具体布局
具体布局设计到一些细节的中央,例如距离,边框,以后组件尺寸设置等一些非凡状况,基本上就是嵌套,一层一层去实现。
代码构造
编码
Index.ets
import Tyre from './tyre_page';
import Temp from './temp_page';
import Battery from './battery_page';
import DoorLook from './door_lock_page';
@Entry
@Component
struct ComponentTest {
@State index: number = 0; // 选项卡下标,默认为第一个
@State hideToolBar: boolean = false;
@State hideTitleBar: boolean = true;
private imageArray: string[] = ['app.media.Lock', 'app.media.Charge', 'app.media.Temp', 'app.media.Tyre',]; // 数据源
@Builder toolbarWidget() { // 通过 builder 自定义 toolbar
Row() {Column() {Image( this.index==0?$r('app.media.lock'):$r('app.media.lock0') )
.size({width: 36, height: 36}).margin({bottom: 4, top: 12})
}
.alignItems(HorizontalAlign.Center)
.height('100%')
.layoutWeight(1)
.onClick(() => {this.index = 0;})
Column() {Image(this.index==1?$r('app.media.battery'): $r("app.media.battery0"))
.size({width: 36, height: 36}).margin({bottom: 4, top: 12})
}
.alignItems(HorizontalAlign.Center)
.height('100%')
.layoutWeight(1)
.onClick(() => {this.index = 1;})
Column() {Image(this.index==2?$r('app.media.yytemp'): $r('app.media.yytem0'))
.size({width: 36, height: 36}).margin({bottom: 4, top: 12})
}
.alignItems(HorizontalAlign.Center)
.height('100%')
.layoutWeight(1)
.onClick(() => {this.index = 2;})
Column() {Image( this.index==3?$r('app.media.tyre'): $r('app.media.tyre0'))
.size({width: 36, height: 36}).margin({bottom: 4, top: 12})
}
.alignItems(HorizontalAlign.Center)
.height('100%')
.layoutWeight(1)
.onClick(() => {this.index = 3;})
}.backgroundColor(Color.Black)
.width('100%')
.height(66)
}
build() {Navigation() {Column({ space: 20}) {
// 依据索引展现对应内容å
if (this.index == 0)
DoorLook()
else if (this.index == 1)
Battery()
else if (this.index == 2)
Temp()
else if (this.index == 3)
Tyre()}
.backgroundColor(Color.Black)
.justifyContent(FlexAlign.SpaceAround)
.alignItems(HorizontalAlign.Center)
.justifyContent(FlexAlign.Center)
.size({width: '100%', height: '100%'})
}
.size({width: '100%', height: '100%'})
.title("跟着坚果学 OpenHarmony")
.toolBar(this.toolbarWidget())// 自定义底部菜单栏
.hideToolBar(this.hideToolBar)
.hideTitleBar(this.hideTitleBar)
.menus([
{
value: "关",
icon: 'common/images/door_lock.svg',
action: () => {console.log("工具栏")
}
},
{
value: "开",
icon: 'common/images/door_unlock.svg',
action: () => {}
}
])
}
}
成果演示:
车锁页
@Entry
@Component
export default struct DoorLook {
// 车锁页
@State isRightDoorLock: boolean = false;
@State isLeftDoorLock: boolean = false;
@State isBonnetLock: boolean = false;
@State isTrunkLock: boolean = false;
build() {Column() {Stack() {Image($r("app.media.Car"))
.width("100%")
.height("100%")
.objectFit(ImageFit.Contain)
.margin({left: 20})
Image($r("app.media.door_lock"))
.width(60).height(60).position({x: 340, y: 50})
.onClick(() => {})
Image($r("app.media.door_unlock")).width(60).height(60).position({x: 50, y: 600})
Image($r("app.media.door_unlock")).width(60).height(60).position({x: 640, y: 600})
Image($r("app.media.door_unlock")).width(60).height(60).position({x: 340, y: 920})
}
.backgroundColor(Color.Black)
.width("100%")
.height("100%")
}
}
}
成果演示:
电池页
@Entry
@Component
export default struct Battery {
// 电池页
build() {Column() {Stack() {Image($r("app.media.Car"))
.width("100%")
.height("80%")
.objectFit(ImageFit.Contain)
.margin({left: 20, top: 150, bottom: 300})
Text("220 mi").fontColor(Color.White).fontWeight(FontWeight.Bold).fontSize(79).position({x: 260, y: 20})
Text("62 %").fontColor(Color.White).fontWeight(FontWeight.Bold).fontSize(60).position({x: 320, y: 90})
Text("22 mi /hr").fontColor(Color.White).fontWeight(FontWeight.Bold).fontSize(45).position({x: 20, y: 1000})
Text("232 v").fontColor(Color.White).fontWeight(FontWeight.Bold).fontSize(45).position({x: 550, y: 1000})
}
.backgroundColor(Color.Black)
.width("100%")
.height("100%")
}
}
}
成果演示:
空调页
@Entry
@Component
export default struct Temp {
// 空调页
build() {Column() {Stack() {Image($r("app.media.Car"))
.width("100%")
.height("100%")
.objectFit(ImageFit.Contain)
.position({x: 268, y: 90})
.margin({left: 20})
Image($r("app.media.Hot_glow_4"))
.width("90%")
.height("90%")
.objectFit(ImageFit.Contain)
.position({x: 220, y: 90})
.margin({left: 20})
Text("29" + "\u2103",).fontSize(90).fontColor(Color.Orange).position({x: 90, y: 400})
Image($r("app.media.arrow_drop_up"))
.width(60)
.height(60)
.position({x: 120, y: 360})
Image($r("app.media.arrow_drop_down"))
.width(60)
.height(60)
.position({x: 120, y: 480})
Image($r("app.media.cool")).width(60).height(60).position({x: 20, y: 40})
Image($r("app.media.heating"))
.width(60)
.height(60)
.position({x: 80, y: 90})
.borderRadius(7)
.margin({right: 40})
Column() {Text("以后温度").fontSize(32).fontColor(Color.White).margin({bottom: 20})
Row({space: 30}) {Column() {Text("外面").fontSize(32).fontColor(Color.Orange)
Text("20" + "\u2103",).fontSize(32).fontColor(Color.White)
}
Column() {Text("外边").fontSize(32).fontColor(Color.Yellow)
Text("35" + "\u2103",).fontSize(32).fontColor(Color.White)
}
}
}.position({x: 20, y: 800})
}
.backgroundColor(Color.Black)
.offset({y: -20})
.width("100%")
.height("100%")
}
}
}
成果演示:
轮胎页
import {TyrePsiCard} from './tyre_psi_card'
@Entry
@Component
export default struct Tyre {
// 轮胎页
build() {Column() {Stack() {Image($r("app.media.Car"))
.width("100%")
.height("80%")
.objectFit(ImageFit.Contain)
.margin({left: 20})
Image($r("app.media.FL_Tyre"))
.width("10%")
.height("10%")
.objectFit(ImageFit.Contain)
.position({x: 180, y: 700})
Image($r("app.media.FL_Tyre"))
.width("10%")
.height("10%")
.objectFit(ImageFit.Contain)
.position({x: 500, y: 700})
Image($r("app.media.FL_Tyre"))
.width("10%")
.height("10%")
.objectFit(ImageFit.Contain)
.position({x: 500, y: 260})
Image($r("app.media.FL_Tyre"))
.width("10%")
.height("10%")
.objectFit(ImageFit.Contain)
.position({x: 180, y: 260})
TyrePsiCard({x: 60, y: 60, boardColor: Color.Blue})
TyrePsiCard({x: 380, y: 60, boardColor: Color.Blue})
TyrePsiCard({x: 60, y: 500, boardColor: Color.Blue, isBottomTwoTyre: false})
TyrePsiCard({x: 380, y: 500, isBottomTwoTyre: false})
}
.backgroundColor(Color.Black)
.width("100%")
.height("100%")
}
}
}
成果演示:
轮胎参数
/**
* 轮胎详细信息
*/
@Entry
@Component
export struct TyrePsiCard {
private text: string = ''
private x: number = 0
private y: number = 0
private boardColor: Color = Color.Red
private isBottomTwoTyre: boolean = true;
build() {Column() {if (this.isBottomTwoTyre) {Text("23.6psi",).fontSize(60)
.fontColor(Color.White).margin({right: 60})
Text("56.0\u2103").fontSize(36)
.fontColor(Color.Orange).margin({bottom: 70})
Text("Low").fontSize(60)
.fontColor(Color.White)
Text("Pressure").fontSize(36)
.fontColor(Color.White)
} else {Text("Low").fontSize(60).margin({right: 60})
.fontColor(Color.White)
Text("Pressure").fontSize(36)
.fontColor(Color.White).margin({bottom: 70})
Text("23.6psi",).fontSize(60)
.fontColor(Color.White)
Text("56.0\u2103").fontSize(36)
.fontColor(Color.Orange)
}
}
.border({
width: 3,
color: this.boardColor
})
.width(280)
.justifyContent(FlexAlign.Start)
.alignItems(HorizontalAlign.Start)
// .padding({left: 10, bottom: 20, top: 20})
.position({x: this.x, y: this.y})
}
}
成果演示:
祝贺你
在本文中,通过实现智联汽车 App 示例,我次要为大家解说了如下 ArkUI(基于 TS 扩大的类 Web 开发范式)组件
容器组件
- Column
- Row
- Stack
根底组件
- Text
- TextInput
- Button
- Image
- Navigation
通用
- 边框设置
- 尺寸设置
- 点击管制
- 布局束缚
- 背景设置
- 点击事件
TS 语法糖
心愿通过本教程,各位开发者能够对以上根底组件具备更粗浅的意识。
前面的打算:
- 一键启动
- 硬件交互
- 动画交互