HarmonyOS NEXT零基础入门到实战-第一部分

构建节页面思路:

1、排版 (分析布局)

2、内容(基础组件)

3、美化(属性方法)

设计资源-svg图标

界面中展示图标 ->可以使用svg图标(任意放大缩小不失真,可以改颜色)

使用方式:

1、设计师提供

2、HarmonyOS图标库中选取

https://developer.huawei.com/consumer/cn/design/harmonyos-icon/

svg图片用法:

Image($r('app.media.ic_dianpu'))

.width(40)

.fillColor('#b0473d')

命名:ic_ 意味着图标

内/外边距

padding/margin

边框border

作用 :给组件添加边界,进行装饰美化。

Text('边框语法')

.fontColor(Color.Red)

.padding(5)

.border({

// 单边框,可以通过 left right bottom top配置四个方法边框

width:1, // 必须设置

color:Color.Red, // 颜色

style:BorderStyle.Solid // 样式(点线,虚线,实线)

})

设置组件圆角

属性:.borderRadius(参数)

参数:数值或对象(四个角单独设置)

特殊形状的圆角设置

正圆 //宽高一样,圆角是宽或高的一半

胶囊按钮(左右半圆) //宽度大高度小,圆角是高的一半

背景属性

背景色

.backgroundColor()

背景图

.backgroundImage()

背景图位置

.backgroundImagePosition({x:100, y:100})

.backgroundImagePosition(Alignment.Center)

单位问题vp2px

背景定位默认单位 -> px:实际的物理像素点【分辨率】

宽高默认单位 --> vp:虚拟像素,相对于不同的设备会自动转换,保证不同设备视觉一直(推荐)

函数:vp2px(数值)

背景图尺寸

.backgroundImageSize

线性布局主轴对齐方式

column和row

column:

排布在主方向上的对齐方式(主轴:垂直往下)

//crtl+p 代码参数提示

.justifyContent(枚举FlexAlign.Start/Center/End/SpaceBetween/SpaceAround/SpaceEvenly)

row:

排布在主方向上的对齐方式(主轴:水平往右)

.justifyContent(枚举FlexAlign.Start/Center/End/SpaceBetween/SpaceAround/SpaceEvenly)

线性布局交叉轴对齐方式

交叉轴对齐方式

alignItems()

column:交叉轴的对齐方式(水平往右)

row:交叉轴的对齐方式(垂直往下)

自适应伸缩:

设置layoutWeight属性的子元素与兄弟元素,会按照权重进行分配主轴的空间

高仿京东登录页

模块拆分:

布局容器+顶部+Logo

思路分析:

1、布局容器:整体从上往下 - Column

2、布局背景 :backgroundImage

3、顶部: 左右布局 -Row、SpaceBetween

4、Logo:Image 图片

输入框和登录区域

思路分析:

1、国家地址:点击区域(Row->Text、Text、Image)

2、手机号:输入框 TextInput

3、同意许可:复选框CheckBox , 文本Text ->Span

4、登录按钮、用户注册

底部模块区域

思路分析:

1、整体column列

2、标题:Text

3、三方登录图标: Row ->Image,SpaceAround

4、底部居底:Blank()填充组件 作用:填充空白区域(像弹簧)

开发技巧:

1、先完成大框架

2、再往下 拆分模块 逐一实现

知识点:

1、复选框 Checkbox

2、一段文本多个样式: Text 包 Span

3、Row 或 Column 空白区域填充:Blank

弹性布局Flex: 又被称为伸缩布局。当子盒子的总和溢出父盒子,默认会进行压缩显示。

1、主轴方向:direction

Flex({

direction:FlexDirection.Row

})

2、主轴对齐方式:justifyContent

Flex({

justifyContent:FlexAlign.Center

})

3、交叉轴对齐方式:alignItems

Flex({

alignItems:ItemAlign.Center

})

单行或者单列的情况,优先还是使用线性布局(本质还是基于Flex设计的,且还做了性能优化)

4、布局换行: wrap

FlexWrap.NoWrap 单行布局

FlexWrap.Wrap 多行布局

Flex({

FlexWrap.NoWrap

})

绝对定位 - position

作用:控制组件位置,可以实现层叠效果

特点:

1、参照 父组件左上角 进行偏移

2、绝对定位后的组件 不再占用自身原有位置

语法:.position({x:1,y:1})

后面的组件明显层级更高,会盖住前面的组件

不动结构的情况下,调整组件的层级 .zIndex() 默认是0

层叠布局

层叠布局具有较强的组件层叠能力。场景:卡片层叠效果等。

特点:层叠操作更简洁,编码效率高。(绝对定位的优势是更灵活)

不动结构的情况下,调整组件的层级 .zIndex() 默认是0

综合案例:

B站-视频卡片

支付宝首页

思路:

1、整体Stack布局 + 底部的tab

2、主题区域的架子: 头部+主体界面(层叠关系、主体界面可滚动)

Column/Row,默认不具备可滚动的效果 -> Scroll

3、头部搜索区域

4、Top快捷按钮区域: Row里面4个Column(layoutWeight)

字符串拼接: +号

模板字符串:更适合于多个变量的字符串拼接

`hello{变量},{变量}`

类型转换:

字符串转数字:

Number(string对象):

parseInt():去掉小数部分转数字

parseFloat():保留小数部分转数字

数字转字符窜:

toString():直接转字符串

toFIxed():四舍五入转字符串,可以保留几位小数

交付:点击事件

监听用户的点击行为,进行对应操作。

onClick((参数) => {

AlertDialog.show({message:'你好~ 这是个弹框'})

})

状态管理

如果希望构建一个动态的、有交互的界面,就需要引入"状态"的概念。

比如说:按钮更新文字(event-handlers 监听交互,修改状态变量(onClick))。

状态变更,自动触发更新。

点击交互 触发了文本状态变更,状态变更引起了UI渲染。

状态变量:

需要装饰器装饰,改变会引起UI的渲染刷新(必须设置类型和初始值)

组件内的变量用必须添加this 全局的不需要添加this

算术运算符(+-*/%)/赋值运算符(= += -+ *= /+/= %=)

点赞案例:

1、注册点击事件 ->onClick

2、点击的适合,修改颜色和数字

提取 颜色/数字 为状态变量

Text:可以放ImageSpan[小icon]和Span

一元运算符:++ --

比较运算符: 用来比较两个数据大小,返回一个布尔值(true/false)

> >= < <= == !=

逻辑运算符:&&:与 || :或 !:取反

作用:扩充判断条件

运算符优先级:

()

++ -- !

算数 先*、/、% 后+,-

比较 > >= < <=

比较 == !=

逻辑运算符: 先&& 后||

赋值 =

美团购物车:

需求分析:

1、商品区域: 数字框 + -

2、底部结算: 联动计算 并渲染展示

已选件数

总价格

优惠价格

核心思路:

1、提取状态 : 数量、原价、现价

2、界面绑定

3、点击修改数据,自动更新

数组的操作

查找&修改:

查找:数组名[下标]

修改:数组名[下标] = 新值

数组长度:数组名.length

增加数组元素:

往开头加: 数组名.unshift(数据1、数据2,...) 返回操作后的数组的长度

结尾添加: 数组名.push(数据1、数据2,...) 返回操作后的数组的长度

删除数组元素:

从开头删:数组名.shift() 返回删除的项

从结尾删:数组名.pop() 返回删除的项

任意位置添加/删除数组元素

语法:数组名.splice(起始位置,删除的个数,新增元素1,新增元素2, ...)

语句:一段可执行的代码,是一个行为(num = a + b)

表达式:可以被求值的代码,并将其计算出一个结果(1+1,3*5,3>2)

语句执行结构:顺序结构,分支结构,循环结构

if分支语句:根据逻辑条件不同,执行不同的语句。 判断范围。

switch多分支:判断值。 default:可以不用加break.

三元表达式:

条件渲染:使用if else和 else if,可基于 不同状态 渲染 对应不同UI内容。

while语句:重复执行指定的一段代码

for循环和for of

for(let item of 数组名) {}

对象数组:

注意:

如果对象的复杂数据,需要在日志中打印,需要调用一个方法,转成字符串格式:JSON.stringify(复杂类型) 对象/数组

访问 + 通过小标

ForEach渲染控制

可以基于数组的个数,渲染组件的个数。(简化代码)

ForEach(数组名,(item:string ,index:number) => {})

阶段案例-生肖抽奖卡

初始布局:

知识点:

1、Badge 角标组件

Badge({

count:1,

position:BadgePosition.RightTop,

style:{

fontSize:12;

badgeSize:16;

badgeColor:'#FACACA'

}

}){Image}

2、Grid 布局

列均匀分布: columnsTemplate('1fr 1fr 1fr')

行均匀分布:rowsTemplate('1fr 1fr 1fr')

数据动态渲染:

1、每个列表项两个数据,一个是图片的地址,一个是抽中的数量

定义接口: 每个列表项的数据结构

interface ImageCount {

url:string

count:number

}

2、基于接口,准备数据

@State images: ImageCount[] = [

{url: '', count:0},

{url: '', count:0}

]

3、Grid 组件 动态渲染

抽卡遮罩层:

思路分析:

1、布局角度: 层叠布局 Stack

2、结构角度: Column > Text + Image + Button

抽大奖遮罩层:

思路分析:

1、布局角度:层叠布局 Stack

2、结构角度:Column > Text + Image + Button

抽大奖显隐控制:

需求说明:六张卡片集齐,显示中大奖页面

思路:

1、准备一个变量,控制显隐

2、每次收下卡片,判断是否集齐,集齐显示中奖页面

随机奖品&再来一次

需求1:奖品随机

需求2:再来一次

思路:

1、奖品随机 --->准备一个奖品数组,Math.random随机取下标

2、再来一次 --->重置数据

知识点:

1、Badge角标组件

2、Grid布局 Stack布局

3、数组对象动态渲染、动态更新

4、遮罩层动画、图像动画效果 animation

5、随机抽奖 Math.random,Math.floor

6、假设成立法,判断是否中奖

相关源代码:

// 1、定义接口(每个列表项的数据结构)

interface ImageCount {

url: string,

count: number

}

// 需求1: 遮罩层显隐 透明度opacity 0 - 1 层级zIndex -1 - 99

// 需求2: 图片缩放 缩放scale: 0 - 1

// 需求3: 随机卡片的选择 0-5 随机数 Math.random 控制展示换图 点击收下,卡片书累加

@Entry

@Component

struct Index {

// 2、基于接口准备数据

@State images: ImageCount[] = [

{ url: 'app.media.bg_00', count: 0 },

{ url: 'app.media.bg_01', count: 0 },

{ url: 'app.media.bg_02', count: 0 },

{ url: 'app.media.bg_03', count: 0 },

{ url: 'app.media.bg_04', count: 0 },

{ url: 'app.media.bg_05', count: 0 }

]

// 控制遮罩层显隐

@State maskOpacity: number = 0 // 透明度

@State maskZIndex: number = -1 // 显示层级

// 控制图片的缩放

@State maskImgX: number = 0 // 水平缩放比

@State maskImgY: number = 0 // 水平缩放比

// 随机的生肖卡序号 0 - 5

@State randomIndex: number = -1 // 表示还没开始抽

// 控制中大奖遮罩的显隐

@State isGet: boolean = false

@State arr: string[] = ['pg', 'hw', 'xm'] // 奖池

@State prize: string = '' // 默认不中奖

build() {

Stack() {

Column() {

Grid() {

ForEach(this.images, (item: ImageCount, index: number) => {

GridItem() {

Badge({

count: item.count,

position: BadgePosition.RightTop,

style: {

fontSize: 14,

badgeSize: 20,

badgeColor: '#fa2a2d'

}

}) {

Image($r(item.url))

.width(80)

}

}

})

}

.columnsTemplate('1fr 1fr 1fr')

.rowsTemplate('1fr 1fr')

.columnsGap(5)

.rowsGap(5)

.width('100%')

.height(300)

.margin({ top: 100 })

Button('立即抽卡')

.width(200)

.backgroundColor('#ed5b8c')

.margin({ top: 50 })

.onClick(() => {

// 点击时修改遮罩参数,让遮罩显示

this.maskOpacity = 1

this.maskZIndex = 99

// 点击时图片需要缩放

this.maskImgX = 1

this.maskImgY = 1

// 计算随机数 Math.random() [0 - 1)小数 向下取整Math.floor

this.randomIndex = Math.floor(Math.random() * 6)

console.log('抽中了', this.randomIndex)

})

}

.width('100%')

.height('100%')

// 抽卡遮罩层(弹层)

Column() {

Text('获得生肖卡')

.fontColor('#f5ebcf')

.fontSize(25)

.fontWeight(FontWeight.Bold)

Image(r(\`app.media.bg_0{this.randomIndex}`))

.width(200)

.margin({ top: 20, bottom: 20 })// 控制元素的缩放

.scale({

x: this.maskImgX,

y: this.maskImgY

})

// 动画 animation,当我们元素有状态的变化,可以添加animation做动画

.animation({

duration: 1000 // 1s

})

Button('开心收下')

.width(200)

.height(50)

.backgroundColor(Color.Transparent)

.border({ width: 2, color: '#fff9e0' })

.onClick(() => {

// 控制弹层显隐

this.maskOpacity = 0

this.maskZIndex = -1

// 图像需要重置缩放比为0 ,方便下一次能够继续缩放

this.maskImgX = 0

this.maskImgY = 0

// 开心收下,对象数组的情况需要更新,需要修改替换整个对象

// this.images[this.randomIndex].count++

// console.log('收下', this.randomIndex, this.images[this.randomIndex].count)

this.images[this.randomIndex] = {

url: `app.media.bg_0${this.randomIndex}`,

count: this.images[this.randomIndex].count + 1

}

// 每次收完卡片,需要进行简单的检索,判断是否集齐

// 需求:判断数组项的count,是否都大于0,只要有一个等于0,就意味着没集齐

let flag: boolean = true //假设集齐

// 验证是否集齐

for (let item of this.images) {

if (item.count == 0) {

flag = false // 没集齐

break // 后面的没必要再进行判断了

}

}

this.isGet = flag

// 判断是否中奖了,如果是,需要抽奖

if (flag) {

// 0 - 2 的值

let randomIndex: number = Math.floor(Math.random() * 3)

this.prize = this.arr[randomIndex]

}

})

}

.justifyContent(FlexAlign.Center)

.width('100%')

.height('100%')

// 设置背景色,颜色十六进制色值,如果是八位,前两位就是透明度

.backgroundColor('#cc000000')

// 设置透明度

.opacity(this.maskOpacity)

.zIndex(this.maskZIndex)

// 动画 animation,当我们元素有状态的变化,可以添加animation做动画

.animation({

duration: 200 // 200ms

})

// 抽大奖的遮罩层 [六张卡片集齐,显示中大奖界面]

if (this.isGet) {

Column({space: 30}) {

Text('恭喜获得手机一部')

.fontColor('#f5ebcf')

.fontSize(25)

.fontWeight(700)

Image(r(\`app.media.{this.prize}`))

.width(300)

Button('再来一次')

.width(200)

.height(50)

.backgroundColor(Color.Transparent)

.border({width: 2 , color: '#fff9e0'})

.onClick(() => {

this.isGet = false

this.prize = ''

this.images = [

{ url: 'app.media.bg_00', count: 0 },

{ url: 'app.media.bg_01', count: 0 },

{ url: 'app.media.bg_02', count: 0 },

{ url: 'app.media.bg_03', count: 0 },

{ url: 'app.media.bg_04', count: 0 },

{ url: 'app.media.bg_05', count: 0 }

]

})

}

.justifyContent(FlexAlign.Center)

.width('100%')

.height('100%')

.backgroundColor('#cc000000')

}

}

}

}

效果图:

相关推荐
康康这名还挺多1 小时前
鸿蒙HarmonyOS list优化一: list 结合 lazyforeach用法
数据结构·list·harmonyos·lazyforeach
gCode Teacher 格码致知1 小时前
《Asp.net Mvc 网站开发》复习试题
后端·asp.net·mvc
晚秋大魔王4 小时前
OpenHarmony 开源鸿蒙南向开发——linux下使用make交叉编译第三方库——nettle库
linux·开源·harmonyos
python算法(魔法师版)8 小时前
.NET 在鸿蒙系统上的适配现状
华为od·华为·华为云·.net·wpf·harmonyos
bestadc9 小时前
鸿蒙 UIAbility组件与UI的数据同步和窗口关闭
harmonyos
枫叶丹410 小时前
【HarmonyOS Next之旅】DevEco Studio使用指南(二十二)
华为·harmonyos·deveco studio·harmonyos next
ax一号街阿楠12 小时前
华为FAT AP配置 真机
网络·华为·智能路由器
吗喽对你问好12 小时前
华为5.7机考第一题充电桩问题Java代码实现
java·华为·排序
乱世刀疤14 小时前
深度 |国产操作系统“破茧而出”:鸿蒙电脑填补自主生态空白
华为·harmonyos
博睿谷IT99_19 小时前
华为HCIP-AI认证考试版本更新通知
人工智能·华为