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

news2025/1/11 17:09:37

构建节页面思路:
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')
      }
    }
  }
}
效果图:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1934487.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Re-labeling ImageNet(CVPR 2021, Naver)

paper&#xff1a;Re-labeling ImageNet: from Single to Multi-Labels, from Global to Localized Labels official implementation&#xff1a;GitHub - naver-ai/relabel_imagenet 背景 ImageNet 数据集是现代计算机视觉领域的重要基准&#xff0c;广泛用于图像分类模型的…

低代码中间件学习体验分享:业务系统的创新引擎

前言 星云低代码平台介绍 星云低代码中间件主要面向企业IT部门、软件实施部门的低代码开发平台&#xff0c;无需学习开发语言/技术框架&#xff0c;可视化开发PC网页/PC项目/小程序/安卓/IOS原生移动应用&#xff0c;低门槛&#xff0c;高效率。针对企业研发部门人员少&#…

从0到1搭建数据中台(4):neo4j初识及安装使用

在数据中台中&#xff0c;neo4j作为图数据库&#xff0c;可以用于数据血缘关系的存储 图数据库的其他用于主要用于知识图谱&#xff0c;人物关系的搭建&#xff0c;描述实体&#xff0c;关系&#xff0c;以及实体属性 安装 在官网 https://neo4j.com/ 下载安装包 neo4j-co…

【jenkins+cmake+svn管理c++项目】msbuild: command not found

一、前言 jenkins中配置cmakeVS的编译构建过程&#xff0c;需要用到MSBuild这个工具来完成VS工作&#xff0c;MSBuild的安装配置方法见&#xff1a;windows编译环境和工具配置 MSBuildCMAKE的编译可以用脚本来完成&#xff0c;我在jenkins的构建步骤中添加了一个ExecuteShell…

Hadoop-36 HBase 3节点云服务器集群 HBase Shell 增删改查 全程多图详细 列族 row key value filter

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; HadoopHDFSMapReduceHiveFlumeSqoopZookeeperHBase 正在 章节内容 上一节我们完成了&#xff1a; 集群的…

解决:Linux上SVN 1.12版本以上无法直接存储明文密码

问题&#xff1a;今天在Linux机器上安装了SVN&#xff0c;作为客户端使用&#xff0c;首次执行SVN相关操作&#xff0c;输入账号密码信息后&#xff0c;后面再执行SVN相关操作&#xff08;比如"svn update"&#xff09;还是每次都需要输入密码。 回想以前在首次输入…

Visual Studio Code 实现远程开发

Background 远程开发是指开发人员在本地计算机上进行编码、调试和测试&#xff0c;但实际的开发环境、代码库或应用程序运行在远程服务器上。远程开发的实现方式多种多样&#xff0c;包括通过SSH连接到远程服务器、使用远程桌面软件、或者利用云开发环境等。这里我们是使用VSCo…

Vue封装文件上传组件(支持图片、PDF、Excel、word预览下载)

一、准备工作 安装预览依赖包&#xff1a;exceljs、mammoth、vue-pdf 二、封装组件 文件上传组件 fileUploadPro.vue。默认预览、下载是true,可通过isPreView、isDownLoad控制 <template><div style"display: flex"><el-uploadmultipleaction&qu…

BUUCTF逆向wp [MRCTF2020]Transform

第一步 查壳。该题为64位。 第二步 进入主函数&#xff0c;跟进dword_40F040,它应该与关键字符串有关 分析一下&#xff1a; 初始化和输入 sub_402230(argc, argv, envp); 这行可能是一个初始化函数&#xff0c;用于设置程序环境或处理命令行参数。具体功能不明&#xff0c…

不同业务场景下通过mars3d实现绕点旋转效果

1.鼠标单击地图某一处就对该点进行绕点旋转效果 相关代码&#xff1a; 1.相关绕点旋转的初始化代码&#xff1a; const rotatePoint new mars3d.thing.RotatePoint({direction: false, // 方向 true逆时针&#xff0c;false顺时针time: 50 // 给定飞行一周所需时间(单位 秒)&…

神经网络中如何优化模型和超参数调优(案例为tensor的预测)

总结&#xff1a; 初级&#xff1a;简单修改一下超参数&#xff0c;效果一般般但是够用&#xff0c;有时候甚至直接不够用 中级&#xff1a;optuna得出最好的超参数之后&#xff0c;再多一些epoch让train和testloss整体下降&#xff0c;然后结果就很不错。 高级&#xff1a;…

使用Docker 实现 MySQL 循环复制(三)

系列文章 使用Docker 实现 MySQL 循环复制&#xff08;一&#xff09; 使用Docker 实现 MySQL 循环复制&#xff08;二&#xff09; 目录 系列文章1. 在主机上安装MySQL客户端2. 配置循环复制拓扑2.1 进入容器2.2 创建复制用户并授予复制权限2.3 复位二进制日志2.4 配置环形复…

Jenkins-zookeeper-docker-xxljob-rancher

文章目录 Jenkins实战1 新建任务需要的配置pipeline Zookeeper基础 Docker基础实操windows11 docker mysql DockerhouseDockerhubxxl-Job基础实战 Rancher基础思考 实战1 Rancher的某个namespace的scale为0 Jenkins 实战 1 新建任务需要的配置pipeline 该代码是Jenkinsfile&…

【Docker】基于Docker-compose创建LNMP环境

目录 一.Docker-compose 概述 1.容器编排管理与传统的容器管理的区别 2.docker-compose 作用 3.docker-compose 本质 4.docker-compose 的三大概念 二.YML文件格式及编写注意事项 1.yml文件是什么 2.yml问价使用注意事项 3.yml文件的基本数据结构 三.Docker-compose …

5G以太网和5G前传业务的有效解决方案——25G可调DWDM光模块

信息技术的迅猛发展和数据传输需求的不断增加&#xff0c;光通信技术在现代网络中扮演着至关重要的角色。DWDM技术通过在一根光纤上使用多个不同波长的光信号同时传输&#xff0c;大幅提高了数据传输的容量。而可调光模块则能够在多种波长之间进行切换&#xff0c;实现灵活、高…

如何用EXCEL自动解方程/方程组?利用 矩阵乘法X=A-*B,X=mmult(minverse(A), B)

目录 问题的由来 1 数据 → 模拟分析 → 单变量求解 1.1 找一个单元格填入公式 1.2 功能入口 1.3 选择单变量求解&#xff0c;分别填入内容 1.4 求解 1.5 这个感觉用处不大 2 重点介绍&#xff0c;用EXCEL进行矩阵运算解方程的操作 2.1 运用EXCEL进行矩阵运算&…

ETL数据集成丨通过ETLCloud工具,将Oracle数据实时同步至Doris中

ETLCloud是一个全面的数据集成平台&#xff0c;专注于解决大数据量和高合规要求环境下的数据集成需求。采用先进的技术架构&#xff0c;如微服务和全Web可视化的集成设计&#xff0c;为用户提供了一站式的数据处理解决方案。 主要特点和功能包括&#xff1a; 实时数据处理&…

Android 使用FFmpeg解析RTSP流,ANativeWindow渲染 使用SurfaceView播放流程详解

文章目录 ANativeWindow 介绍ANativeWindow 的主要功能和特点ANativeWindow 的常用函数工作流程原理图通过ANativeWindow渲染RGB纯色示例 播放RTSP流工作流程图关键步骤解析自定义SurfaceView组件native 层解码渲染 效果展示注意事项 这篇文章涉及到jni层&#xff0c;以及Ffmpe…

pdf提取其中一页怎么操作?提取PDF其中一页的方法

pdf提取其中一页怎么操作&#xff1f;需要从一个PDF文件中提取特定页码的操作通常是在处理文档时常见的需求。这种操作允许用户选择性地获取所需的信息&#xff0c;而不必操作整个文档。通过选择性提取页面&#xff0c;你可以更高效地管理和利用PDF文件的内容&#xff0c;无论是…

负载均衡 lvs

1. 4层转发(L4) 与 7层转发(L7) 区别 4层转发(L4) 与 7层转发(L7) 区别 转发基于的信息 状态 常用的服务 L4 基于网络层和传输层信息&#xff1a; L4转发主要依赖于网络层IP头部(源地址&#xff0c;目标地址&#xff0c;源端口&#xff0c;目标端口)和传输层头部&#xff…