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')

}

}

}

}

效果图:

相关推荐
SoraLuna3 小时前
「Mac畅玩鸿蒙与硬件47」UI互动应用篇24 - 虚拟音乐控制台
开发语言·macos·ui·华为·harmonyos
AORO_BEIDOU7 小时前
单北斗+鸿蒙系统+国产芯片,遨游防爆手机自主可控“三保险”
华为·智能手机·harmonyos
博览鸿蒙8 小时前
鸿蒙操作系统(HarmonyOS)的应用开发入门
华为·harmonyos
Damon小智15 小时前
HarmonyOS NEXT 技术实践-基于基础视觉服务的多目标识别
华为·harmonyos
m0_6632340118 小时前
在 .NET 5.0 运行 .NET 8.0 教程:使用 ASP.NET Core 创建 Web API
前端·asp.net·.net
匹马夕阳18 小时前
华为笔记本之糟糕的体验
华为·笔记本电脑
egekm_sefg18 小时前
华为、华三交换机纯Web下如何创关键VLANIF、操作STP参数
网络·华为
岳不谢1 天前
华为DHCP高级配置学习笔记
网络·笔记·网络协议·学习·华为
爱笑的眼睛111 天前
uniapp 极速上手鸿蒙开发
华为·uni-app·harmonyos
K.P1 天前
鸿蒙元服务从0到上架【第三篇】(第二招有捷径)
华为·harmonyos·鸿蒙系统