HarmonyOS鸿蒙开发学习:鸿蒙基础-基础环境-ArkTS-组件-样式

鸿蒙基础-基础环境-ArkTS-组件-样式

DevEcoStudio编辑器下载链接
链接: https://pan.baidu.com/s/18C9i35YPh4GsHpbSif8KQw?pwd=d6e9 提取码: d6e9

安装教程

下载对应的版本

  • windows
  • mac英特尔
  • mac Arm

API12 的编辑器
API12的模拟器(mac英特尔安装API11)

  • Mac Arm芯片版本安装

解压编辑器版本
image.png

image.png

将左侧内容拖入

image.png

点击打开

  • 打开项目的配置项

image.png
image.png

新建一个路径 HarmonyOS-SDK
将资源下载包中的sdk的内容进行解压,放入到刚刚新建的目录
image.png
将设置中的安装路径改变成新建的目录,最终点击确认,sdk就安装好了

image.png

打开原有项目发现
image.png

一个配置文件的依赖,线上没有提供云下载地址,只能采用离线的版本 。hvigor

下载资源包中,还有提供一个dependencies, 这就是我们需要替换的版本
image.png
image.png
image.png
image.png

安装模拟器

  • 需要实名登录

image.png

  • 安装插件

image.png
image.png

internal-plugin-SNAPSHOT.zip
如果大家的mac安装不上 这个插件,可以采用文档中提供的,下载之后安装即可

image.png

下载资源中的模拟器,拷贝到sdk的目录
注意: 模拟器的名字是小写的
image.png

  • 创建镜像目录

注意
** 如果用的是API12的模拟器,需要把镜像放入到HarmonyOS-NEXT-DB1 目录下。**
** 如果用的是API11的模拟器,需要把镜像放入到HarmonyOS-NEXT-DP2 目录下。**

system-image
HarmonyOS-NEXT-DB1
phone_arm/phone_x86
HarmonyOS-NEXT-DP2
phone_arm/phone_x86

image.png

Windows安装模拟器

起步

起步-鸿蒙简介

  • HarmonyOS 是新一代的智能终端操作系统,为不同设备的智能化、互联与协同提供了统一的语言。带来简洁,流畅,连续,安全可靠的全场景交互体验。

历程:

时间 事件
2019 HarmonyOS 1.0,华为在东莞举行华为开发者大会,正式发布操作系统鸿蒙 OS,主要用于物联网
2020 HarmonyOS 2.0,基于开源项目 OpenHarmony 开发的面向多种全场景智能设备的商用版本
2021 HarmonyOS 3.0,先后优化游戏流畅度、地图三维体验、系统安全,另外系统的稳定性也得到了增强
2023.2 HarmonyOS 3.1,系统纯净能力进一步提升,对后台弹窗、 隐藏应用、后台跳转等情况
2023.7 华为 Mate 50 系列手机获推 HarmonyOS 4.0
2024 HarmonyOS Next 开发者预览版发布,将不在兼容安卓应用

起步-DevEco Studio

image.png

安装 DevEco Studio 编辑器

DevEcoStudio编辑器下载链接
链接: https://pan.baidu.com/s/1TyrmbTkrOEsTB8HcaMR4og?pwd=fjjw 提取码: fjjw

  1. 安装:DevEco Studio → 一路 Next(只演示windows)

image.png
image.png
image.png
image.png
image.png
image.png

  1. 运行: 选择not import System Img

这里最好别选在C盘

  • 下一步

image.png
image.png

  • 下载sdk

image.png

  • 安装完成

image.png

  • 安装完成

image.png

  • 创建一个新项目

image.png

  • 填写信息

image.png
等待创建完成

  • 安装中文插件(windows)

image.png

  • Mac的选择

image.png

  • 选择Plugins

image.png

  • 点OK重启

image.png

  • 看到效果

image.png

起步-认识工作区

image.png

  • 通过左侧目录找到对应的应用文件,在编辑区进行代码编写,在右侧看预览效果
  • 连按两下shift,可以快速寻找文件

起步-如何排错

image.png

写代码时,我们会经常遇到这种情况,右侧出现不能够开启预览器的提示,让我们打开预览器日志看错误

  • 解决该问题的思路 1. 按照编辑器提示的,打开预览器日志

image.png

  • 如果是明确的语法错误或者api错误,编辑器会指出我们代码的行数,我们可以点击提示的代码行,直接跳到对应位置,直接检查代码的问题

image.png

  • 跳到对应的位置

image.png

解决思路2: 如果当前文件不多,可以点开你创建的所有文件,查看文件中是否有报错的地方,文件报错,在右侧以及代码区会有明显的报错提示
image.png

解决思路3: 通过统一构建,暴露哪些文件及代码无法编译通过
image.png

image.png

如何刷新看效果

预览器是有热更新的

  • 原则上写完右侧自动更新
  • 如果不自动刷新- 语法错了,编辑器卡住了

image.png

  • 直接点击刷新按钮

image.png

  • 刷新只能针对 带有@Entry和@Preview的文件,否则无法看到效果

起步-审查和多设备预览

效果预览方法:
info

  • Preview(预览器)
  • 本地模拟器(只有Mac(ARM)芯片)
  • 远程模拟器
  • 云手机(需要审核及申请,暂无消息)
  • 本地真机(Meta60-Meta60Pro X5或者是装载OpenHarmony的工程机(价格较低,但是依然存在一些问题))

danger
只有装了Next预览版系统的手机才可以进行真机调试和预览,目前Next预览器系统装机量有限,需要申请和审核,小道消息Q2季度会进一步扩大开放名额

  • 预览器的多设备预览

image.png
danger
2in1的意思是 平板电脑二合一的状态

未命名.gif

  • 审查元素

image.png

image.png

  • 真机预览调试

image.png
info

  • 刷了Next预览版本的手机插上数据线,连接到电脑之后(注意:这里需要开启手机的usb调试,设置中搜索usb调试,打开,并且处理开发者模式,打开手机设置-关于手机,连续点击手机系统的版本号,直到出现您已处于开发者模式的提示未知)

  • 运行
    info
    点击绿色三角- 运行到真机

  • debugger模式
    info
    点击小虫子-断点调试到真机(4.0版本中真机不支持断点调试-next真机支持断点调试)

起步-工程目录结构

image.png

info
我们详解下目录结构

  • AppScope > app.json5:应用的全局配置信息。

  • **entry:**应用/服务模块,编译构建生成一个HAP。

    • src > main > ets:用于存放ArkTS源码。
    • src > main > ets > entryability:应用/服务的入口。
    • src > main > ets > pages:应用/服务包含的页面。
    • **src > main > resources:**用于存放应用/服务模块所用到的资源文件,如图形、多媒体、字符串、布局文件等。
    • src > main > module.json5:Stage模型模块配置文件,主要包含HAP的配置信息、应用在具体设备上的配置信息以及应用的全局配置信息。
  • **entry > build-profile.json5:**当前的模块信息、编译信息配置项,包括buildOption、targets配置等。

  • entry > hvigorfile.ts:模块级编译构建任务脚本。

  • entry >oh-package.json5:配置三方包声明文件的入口及包名。

  • oh_modules:用于存放三方库依赖信息,包含应用/服务所依赖的第三方库文件。关于原npm工程适配ohpm操作,请参考历史工程适配OHPM包管理

  • **build-profile.json5:**应用级配置信息,包括签名、产品配置等。

  • **hvigorfile.ts:**应用级编译构建任务脚本。

  • 资源目录结构

image.png

什么是Stage模型

info
通过上层的目录结构我们要分析出如下关系
State
-Module(模块-对应Hap包)
-ability(应用服务入口)
-pages(页面)
-component(自定义组件)
-resources(资源)

image.png

应用模型Stage&FA

鸿蒙的战略 兼容安卓-把java + 前端拉入到开发阵容中-FA模型

官方介绍

  • 应用模型是HarmonyOS为开发者提供的应用程序所需能力的抽象提炼,它提供了应用程序必备的组件和运行机制。有了应用模型,开发者可以基于一套统一的模型进行应用开发,使应用开发更简单、高效。

换言之- 应用模型是鸿蒙开发一切的基础,因为只有基于该应用模型我们才可以开发对应的应用和业务。

应用模型包含几个要素**应用组件-**应用进程-应用线程-应用任务管理-应用配置文件

提问:应用模型是只有一个吗?
回答:鸿蒙前后推出了两种应用模型- FA(Feature Ability),Stage,目前FA已经不再主推

image.png

  • HarmonyOS Next也将Stage模型作为主推模型,所以我们本次训练营将学习Stage模型相关的应用开发能力。

下面是官方的Stage模型概念图
image.png

总结:应用模型是开发鸿蒙应用的基础底座,但是鸿蒙先后推出了FA和Stage,鸿蒙4.0和鸿蒙Next都将Stage作为主推方向,所以我们主要基于Stage模型来学习和开发我们目前的应用

什么是UIAbility-(界面能力组件)

从上一个小节中,我们发现Stage模型提到了UIAbility组件包含UI界面绘制,主要和用户交互。

  • UIAbility组件是一种包含UI界面的应用组件,主要用于和用户交互。

官网介绍-UIAbility是系统调度的基本单元,可以给应用提供绘制界面的窗口。
info
UIAbility的设计理念:

  1. 原生支持应用组件级的跨端迁移和多端协同。
  2. 支持多设备和多窗口形态。

UIAbility组件是系统调度的基本单元,为应用提供绘制界面的窗口。一个应用可以包含一个或多个UIAbility组件。例如,在支付应用中,可以将入口功能和收付款功能分别配置为独立的UIAbility。

每一个UIAbility组件实例都会在最近任务列表中显示一个对应的任务。

image.png

对于开发者而言,可以根据具体场景选择单个还是多个UIAbility,划分建议如下:

  • 如果开发者希望在任务视图中看到一个任务,则建议使用一个UIAbility,多个页面的方式。

  • 如果开发者希望在任务视图中看到多个任务,或者需要同时开启多个窗口,则建议使用多个UIAbility开发不同的模块功能。

  • 场景- 支付/小程序/鉴权

为使应用能够正常使用UIAbility,需要在module.json5配置文件abilities标签中声明UIAbility的名称、入口、标签等相关信息。

{
   
  "module": {
   
    ...
    "abilities": [
      {
   
        "name": "EntryAbility", // UIAbility组件的名称
        "srcEntry": "./ets/entryability/EntryAbility.ets", // UIAbility组件的代码路径
        "description": "$string:EntryAbility_desc", // UIAbility组件的描述信息
        "icon": "$media:icon", // UIAbility组件的图标
        "label": "$string:EntryAbility_label", // UIAbility组件的标签
        "startWindowIcon": "$media:icon", // UIAbility组件启动页面图标资源文件的索引
        "startWindowBackground": "$color:start_window_background", // UIAbility组件启动页面背景颜色资源文件的索引
        ...
      }
    ]
  }
}

warning
上述文件不用我们手动填写,我们新建ability的时候,会自动填入

组件基础

组件-什么是ArkTS

info
ArkTS提供了语言运行时相关能力
ArkTS是HarmonyOS优选的主力应用开发语言。ArkTS围绕应用开发在TypeScript(简称TS)生态基础上做了进一步扩展,保持了TS的基本风格,同时通过规范定义强化开发期静态检查和分析,提升程序执行稳定性和性能。

特别注意:尤其是学过鸿蒙4.0的,Next版本极大增强了TS语言中动态类型的限制,几乎不再支持动态类型

从API version 10开始,ArkTS进一步通过规范强化静态检查和分析,对比标准TS的差异可以参考从TypeScript到ArkTS的适配规则

  • 强制使用静态类型:静态类型是ArkTS最重要的特性之一。如果使用静态类型,那么程序中变量的类型就是确定的。同时,由于所有类型在程序实际运行前都是已知的,编译器可以验证代码的正确性,从而减少运行时的类型检查,有助于性能提升。
  • 禁止在运行时改变对象布局:为实现最大性能,ArkTS要求在程序执行期间不能更改对象布局。
  • 限制运算符语义:为获得更好的性能并鼓励开发者编写更清晰的代码,ArkTS限制了一些运算符的语义。比如,一元加法运算符只能作用于数字,不能用于其他类型的变量。
  • 不支持Structural typing:对Structural typing的支持需要在语言、编译器和运行时进行大量的考虑和仔细的实现,当前ArkTS不支持该特性。根据实际场景的需求和反馈,我们后续会重新考虑。
  • 由于文档权限的限制,这里有一份openHarmony的 上的Next版本的ts类型的迁移说明 地址 (内容基本一致)

openHarmony 和HarmonyOS的关系和区别
OpenHarmony是指鸿蒙(HarmonyOS)的开源版本,由华为官方开源,遵循Apache 2.0许可证。OpenHarmony包含了HarmonyOS的核心代码库,但并不包括商业版HarmonyOS中的一些特有功能和技术。
HarmonyOS是华为自主研发的分布式操作系统,旨在打造一个全场景、全终端的智能生态系统。它支持多种设备类型,包括手机、平板、智能手表、智能音箱、电视、汽车、家居等,可以实现设备之间的协同工作和资源共享。
OpenHarmony和HarmonyOS的关系就像是Java和Android的关系一样。可以将OpenHarmony看作是HarmonyOS的底层技术和代码库的一部分,而HarmonyOS则是在此基础上进行了更多的开发和扩展,添加了更多的功能和应用。相比之下,OpenHarmony更加开放和自由,可以被开发者用于构建各种类型的设备和应用,而HarmonyOS则更加注重整合、统一和优化整个生态系统。

image.png

  • ArkTS的特性-扩展能力
  1. **基本语法 **
    • 定义声明式UI、自定义组件、动态扩展UI元素;
    • 提供ArkUI系统组件,提供组件事件、方法、属性;
    • 共同构成 UI 开发主体
  2. **状态管理 **
    • 组件状态、组件数据共享、应用数据共享、设备共享;
  3. **渲染控制 **
    • 条件渲染、循环渲染、数据懒加载;

ArkTS以声明方式组合和扩展组件来描述应用程序的UI,同时还提供了基本的属性、事件和子组件配置方法,帮助开发者实现应用交互逻辑。

  • 命令式UI- document.createElement(“div”)-
  • 声明式UI

image.png

下图是关于ArtTS的一个整体的应用架构(官网)
image.png

info
总结:

  • AktTS提供原有前端范畴内的一切TypeScript和JavaScript的类型及方法支持
  • Next版本加了很多限制-要看迁移指南
  • ArkTS采用声明式UI的方法来绘制页面,设置属性,绑定事件

ArkTS重点迁移说明

  • 对象字面量不能用于类型声明

image.png

  • 不支持in操作符

image.png

  • 不支持解构赋值

image.png

  • 不支持通过索引访问字段

image.png
image.png

有一种情况下,可以通过索引访问字段,即传入的参数类型为object, 但是传入时必须用class的类型传入,如下

@Entry
@Component
struct Index {
   
  @State message: string = 'Hello World1';
  test (obj: object) {
   
   console.log(Object.keys(obj).map(item => `${
     item}=${
     obj[item]}`).toString())
  }
  aboutToAppear(): void {
   
    let o = new TestObj()
    this.test(o)
  }
  build() {
   
    Row() {
   
      Column() {
   
        Text(this.message)
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
      }
      .width('100%')
    }
    .height('100%')
  }
}
class TestObj {
   
  a: number = 0
  b: string = "123"
}

以上场景一般用作请求封装时,无法确定侦测传入参数的类型时使用

  • 部分支持延展运算符

image.png

  • 不支持bind/call/apply改变this指向

this始终指向调用者。谁调用这个方法,this指向谁

image.png

基础-组件结构

info
接下来,我们来解析我们的UI的结构

image.png

ArkTS通过装饰器 @Component@Entry 装饰 struct 关键字声明的数据结构,构成一个自定义组件。
自定义组件中提供了一个 build 函数,开发者需在该函数内以链式调用的方式进行基本的 UI 描述,UI 描述的方法请参考 UI 描述规范。

  • struct-自定义组件基于struct实现

要想实现一段UI的描述,必须使用struct关键字来声明- 注意不能有继承关系-组件名不能系统组件名重名

语法: struct 组件名 {}

@Component
struct Index {
   
  
}
@CustomDialog 
struct Index2 {
   
  
}

info
struct关键字声明的UI描述-必须被@Component或者@CustomDialog修饰

  • Component修饰符

Component装饰器只能修饰struct关键字声明的结构,被修饰后的struct具备组件的描述(渲染)能力

  • build函数

用于定义组件的UI描述,一个struct结构必须实现build函数

@Component
struct MyComponent {
   
  build() {
   
  }
}

info
注意:
1.build函数是组件(Component)必须提供以及实现的一个函数,build函数可以没有内容,如果有的话,必须有且只有一个容器组件(可以放置子组件的组件)- 只有entry里面有限制- component里面没有限制
2.Component的组件build函数 可以放没有子组件的组件
image.png

  • 常见容器组件- Flex-Column-Row-List-Grid-Panel

  • entry修饰符

entry将自定义组件定义为UI页面的入口,也就是我们原来前端常说的一个页面,最多可以使用entry装饰一个自定义组件(在一个ets文件中)-如下面的代码就是不被允许的

@Entry
@Component
struct Index {
   

  build() {
   
  
  }
}
@Entry
@Component
struct Index2 {
   
  build() {
   

  }
}

info
entry修饰的组件,最终会被注册,具体文件位置-main/resources/base/profile/main_pages.json

  1. 自动注册-新建组件时,采用新建Page的方式
  2. 手动注册-新建一个ets文件,自己在main_pages.json中手动添加路径

注意:
如果你手动删除了某一个带entry的组件,你需要手动去main_page中去删除该路径,否则编译会报错

  • 组件复用

在很多情况下,由于业务的复杂度,我们经常会将一个大的业务拆成若干个组件,进行组装,这里我们非常灵活的复用组件,比如

image.png

info

  • 我们可以把上图抽象成三个组件- Header- Main- Footer

代码

import {
    MeiTuanFooter } from '../views/MeiTuan/MeiTuanFooter';
import {
    MeiTuanHeader } from '../views/MeiTuan/MeiTuanHeader';
import {
    MeiTuanMain } from '../views/MeiTuan/MeiTuanMain';

@Entry
@Component
struct MeiTuan {
   
  @State message: string = 'Hello World';

  build() {
   
    Column() {
   
      MeiTuanHeader()  // 60
      MeiTuanMain()
        .layoutWeight(1)
        .backgroundColor(Color.Green)
      MeiTuanFooter()  // 60
    }.height('100%')
  }
}

@Preview
@Component
struct MeiTuanHeader {
   
  build() {
   
    Row () {
   
      Text("美团头部")
        .width('100%')
        .textAlign(TextAlign.Center)
    }
    .width('100%')
    .height(60)
    .backgroundColor(Color.Pink)
  }
}
export {
    MeiTuanHeader }
@Component
struct MeiTuanMain {
   
  build() {
   
    Row() {
   
      Text("美团中部")
        .fontColor(Color.Red)
    }
    .justifyContent(FlexAlign.Center)
    .width('100%')
  }
}

export {
    MeiTuanMain }

@Component
struct MeiTuanFooter {
   
  build() {
   
    Row () {
   
      Text("美团底部")
        .fontColor(Color.White)
    }
    .justifyContent(FlexAlign.Center)
    .width('100%')
    .height(60)
    .backgroundColor(Color.Blue)
  }
}
export  {
    MeiTuanFooter  }

image.png

info
总结:

  • 一个UI描述必须使用struct来声明,不能继承
  • struct必须被Component或者CustomDialog修饰
  • struct必须实现build方法,build方法可以没有元素,但是有的话有且只有一个可容纳子组件的容器组件(entry修饰的组件)
  • entry修饰符表示该组件是页面级组件,一个文件中只允许修饰一个struct组件
  • 采用分拆组件的形式可以有效解解耦我们的业务

基础-系统组件(ArkUI)

ArkUI: Ability Kit在UIAbility组件可以使用ArkUI提供的组件、事件、动效、状态管理等能力。
这里所指的Kit其实是Next版本中,鸿蒙将各个能力集进行了统一的分类

ArkUI将组件大概分为这么几类

  • 基础组件
  • 容器组件
  • 媒体组件(只有一个Video)
  • 绘制组件
  • 画布组件
  • 高级组件 额外新增
  • 安全组件 额外新增

大家关心的地图功能在Next版本中以API形式呈现
image.png

基本组件使用

  • Text 文本组件-(Span子组件 ImageSpan组件)
  • Column 列组件,纵向排列,Flex布局主轴是Y (任意子组件)
  • Row 行组件,横向排列,Flex布局主轴是X (任意子组件)
  • Flex 以弹性方式布局子组件的容器组件。(存在二次布局,官方推荐有性能要求,使用Column和Row代替) (任意子组件)
  • Button 按钮组件 (单子组件)
  • TextInput 输入框组件 (无子组件)
  • Image (无子组件)
  • Button (单个子组件)
  • List (仅支持ListItem子组件)
  • Scroll (仅支持单个子组件)
  • Stack(堆叠容器,子组件按照顺序依次入栈,后一个子组件覆盖前一个子组件)
  • Grid(网格容器,由“行”和“列”分割的单元格所组成,通过指定“项目”所在的单元格做出各种各样的布局。仅支持GridItem组件)
  • GridRow(栅格容器组件,仅可以和栅格子组件(GridCol)在栅格布局场景中使用。)
  • GirdCol(栅格子组件,必须作为栅格容器组件(GridRow)的子组件使用。)

组件使用
info

  • 使用组件采用 **组件名() **的语法
  • 有构造参数采用 **组件名(参数)**的语法
  • 组件里放置子组件采用 **组件名() { 子组件的语法 } **的链式语法
  • 组件设置属性采用 **组件名().width().height() **的语法
  • 组件又有属性又有子组件采用 **组件名(){ … 子组件 }.width().height() **的语法

基础布局

横向布局-采用Row
百分比说明: 鸿蒙的里面的百分比指的是相对当前父容器,并不是当前的手机屏幕
在写宽度高度时,直接写数字默认单位为vp虚拟像素,屏幕会进行适配。

image.png

Row组件默认情况下,子组件内容会垂直方向居中-** 内容超出不会换行**

@Entry
@Component
struct ComponentCase {
   
  @State message: string = 'Hello World'

  build() {
   
    Column() {
   
      // css 支持调整布局
      Row({
    space: 15 }) {
   
        Column()
          .width(100)
          .height(200)
          .backgroundColor(Color.Pink)
        Column()
          .width(100)
          .height(200)
          .backgroundColor(Color.Red)
        Column()
          .width(100)
          .height(200)
          .backgroundColor(Color.Blue)
      }
      .width('100%')
      // .justifyContent(FlexAlign.Start)

      .justifyContent(FlexAlign.Center)

      // .justifyContent(FlexAlign.End)
      // .justifyContent(FlexAlign.SpaceBetween)
      // .justifyContent(FlexAlign.SpaceAround)
      // .justifyContent(FlexAlign.SpaceEvenly)
    }
    .width('100%')
    .height('100%')
  }
}

纵向布局

image.png

@Entry
@Component
struct ComponentCase {
   
  @State message: string = 'Hello World'

  build() {
   
    Column({
    space: 10 }) {
   
      // css 支持调整布局
      Row({
    space: 15 }) {
   
        Column()
          .width(100)
          .height(200)
          .backgroundColor(Color.Pink)
        Column()
          .width(100)
          .height(200)
          .backgroundColor(Color.Red)
        Column()
          .width(100)
          .height(200)
          .backgroundColor(Color.Blue)
      }
      .width('100%')
      // .justifyContent(FlexAlign.Start)
      .justifyContent(FlexAlign.Center)

      Column({
    space: 15 }) {
   
        Column()
          .width(200)
          .height(100)
          .backgroundColor(Color.Pink)
        Column()
          .width(200)
          .height(100)
          .backgroundColor(Color.Red)
        Column()
          .width(200)
          .height(100)
          .backgroundColor(Color.Blue)
      }
      .width('100%')
      .justifyContent(FlexAlign.Center)

    }
    .width('100%')
    .height('100%')
  }
}

自定义组件应用

@Entry
@Component
struct Layout {
   

  build() {
   
    Column() {
   
      RowCase()
      ColumnCase()
    }.height('100%').backgroundColor(Color.Grey)
  }
}

@Component
struct RowCase {
   
  build() {
   
    Row() {
   
      Column().height(150).width(100).backgroundColor(Color.Pink)
      Column().height(150).width(100).backgroundColor(Color.Red)
      Column().height(150).width(100).backgroundColor(Color.Blue)
    }
    .width('100%')
    .alignItems(VerticalAlign.Top)
    .justifyContent(FlexAlign.SpaceAround)
  }
}

@Component
struct ColumnCase {
   
  build() {
   
    Column() {
   
      Column().height(100).width(150).backgroundColor(Color.Pink)
      Column().height(100).width(150).backgroundColor(Color.Red)
      Column().height(100).width(150).backgroundColor(Color.Blue)
    }.height(400).width('100%').justifyContent(FlexAlign.SpaceEvenly)
  }
}
  • 百度的小案例

image.png

@Entry
@Component
struct Baidu {
   

  build() {
   
    Column({
    space: 20 }) {
   
      Image("https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png")
        .width(160)
      Row() {
   
        TextInput()
          .borderRadius({
   
            topLeft: 6,
            bottomLeft: 6
          })
          .height(40)
          .layoutWeight(1)
          .backgroundColor(Color.White)
          .border({
   
             color: "#c4c7ce",
             width: 2
          })
        Button("百度一下")
          .type(ButtonType.Normal)
          .backgroundColor("#516aee")
          .padding({
   
            left: 10,
            right: 10,
            top: 6,
            bottom: 6
          })
          .translate({
   
            x: -2
          })
          .borderRadius({
   
            topRight: 6,
            bottomRight: 6
          })
      }
      .padding({
   
        left: 10,
        right: 10
      })
      .width('100%')
    }
    .justifyContent(FlexAlign.Center)
    .width('100%')
    .height('100%')
  }
}

warning
Row 和Column的布局方式成为线性布局- 不是横向排列就是纵向排列

  • 线性布局中永远不会产生换行
  • 均不支持出现滚动条
  • 横向排列的垂直居中,总行排列的水平居中
  • 主轴-排列方向的轴
  • 侧轴-排列方向垂直的轴

堆叠布局

image.png
info
只要在Stack内部-后者永远会覆盖前者

image.png

@Entry
@Component
struct Baidu {
   
  build() {
   
    Column({
    space: 12 }) {
   
      //   图片
      Row() {
   
        Stack({
   alignContent:Alignment.TopEnd}) {
   
          Image('https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png')
            .width(160)
          Text('鸿蒙版')
            .fontSize(12)
            .offset({
   
              x:-20,
              y:30
            })
        }
      }
      .width('100%')
      .justifyContent(FlexAlign.Center)

      //   输入框+按钮
      Row() {
   
        TextInput()
          .layoutWeight(1)
          .border({
   
            width: 2,
            color: '#ccc'
          })
          .height(40)
          .borderRadius({
   
            topLeft: 4,
            bottomLeft: 4
          })
          .backgroundColor('#fff')
        Button('百度一下')
          .type(ButtonType.Normal)
          .translate({
   
            x: -2
          })
          .borderRadius({
   
            topRight: 4,
            bottomRight: 4
          })
      }
    }
    .width('100%')
    .height('100%')
    .padding(16)
    .justifyContent(FlexAlign.Center)
  }
}

info
Stack的参数 可以设置子组件的排列方式-alignContent

  • Top(顶部)
  • TopStart(左上角)
  • TopEnd(右上角)
  • Start(左侧)
  • End(右侧)
  • Center(中间)
  • Bottom(底部)
  • BottomStart(左下角)
  • BottomEnd(右下角)

image.png

@Entry
@Component
struct FontJump {
   
  build() {
   
    Row() {
   
      Stack() {
   
        Text('抖音')
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
          .fontColor('#ff2d83b3')
          .translate({
   
            x:-2,
            y:2
          })
          .zIndex(1)
        Text('抖音')
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
          .fontColor('#ffe31fa9')
          .translate({
   
            x:2,
            y:-2
          })
          .zIndex(2)

        Text('抖音')
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
          .fontColor('#ff030000')
          .translate({
   
            x:0,
            y:0
          })
          .zIndex(3)

      }
      .width('100%')
    }
    .height('100%')
  }
}

弹性布局

image.png

@Entry
@Component
struct ComponentCase {
   
  @State message: string = 'Hello World'
  build() {
   
    Scroll() {
   
      Row() {
   
        Column() {
   
          Flex({
    direction: FlexDirection.Row, justifyContent: FlexAlign.SpaceAround }) {
   
            Column()
              .width(100)
              .height(200)
              .backgroundColor(Color.Pink)
            Column()
              .width(100)
              .height(200)
              .backgroundColor(Color.Red)
            Column()
              .width(100)
              .height(200)
              .backgroundColor(Color.Blue)
          }
          .margin({
   
            top: 200
          })

        }
        .width('100%')
      }
    }

  }
}

warning
Flex布局设置属性设置方向 是通过参数的,并非通过属性

  • 属性?

image.png

  • 参数?

image.png

网格布局

Grid布局

  • 想要控制屏幕的分栏 分几列, 怎么分 特别像前端的栅格布局
  • Row组件默认情况下,里面的元素的纵向是居中的
  • Column组件默认横向是居中的

image.png

info
Grid组件下只能放置GridItem组件

Grid可以设置columnsTemplate和rowsTemplate
columnsTemplate是设置横向的分配,如果设置 1fr 1fr 表示,等分为两份, 如果设置1fr 2fr表示左边一份,右边两份, 在设置columnsTemplate不设置rowsTemplate的情况下,如果内容超出容器区域,会自动出现滚动条 columnsGap设置列和列之间的间距,rowsGap设置行和行之间的间距

@Entry
@Component
struct GridCase {
   
  build() {
   
    Grid() {
   
      GridItemCase()
      GridItemCase()
      GridItemCase()
      GridItemCase()
      GridItemCase()
      GridItemCase()
      GridItemCase()
      GridItemCase()
      GridItemCase()
      GridItemCase()
      GridItemCase()
      GridItemCase()
      GridItemCase()
      GridItemCase()
      GridItemCase()
      GridItemCase()
      GridItemCase()
    }
    .width("100%")
    .height("100%")
    .columnsTemplate("1fr 1fr")
    .columnsGap(10)
    .rowsGap(10)
    .padding(10)

  }
}

@Component
struct GridItemCase {
   
  build() {
   
    GridItem() {
   
      Row() {
   
        Column() {
   
          Text("内容")
        }
        .width('100%')
      }
      .height(200)
      .borderRadius(4)
      .backgroundColor(Color.Pink)
    }

  }
}

滚动条说明

在基本的布局组件 Column/Row/Flex/Stack中不论内容超出与否,皆不会出现滚动条

  • 出现滚动条的组件
  • Grid
  • List(列表)
  • Scroll(滚动条)
  • Swiper(轮播)
  • WaterFlow(瀑布流)

出现滚动条的前提条件是- 上述组件中的子组件的内容超出了父容器组件的宽度或者高度

  • 使用最基本的Scroll组件出现一个滚动条

image.png

  • 先实现基本的布局
@Entry
@Component
struct ScrollCase {
   
  build(
### 鸿蒙系统 `background-size` 属性详解 #### 背景介绍 在鸿蒙系统的样式设计中,`background-size` 是一个重要的 CSS 属性,用于控制背景图像的尺寸大小。合理配置此属性可以显著提高界面美观度和用户体验。 #### 使用方法 `background-size` 的基本语法如下: ```css background-size: <length> | <percentage> | cover | contain; ``` - `<length>` 可以指定具体的像素值或相对单位; - `<percentage>` 表示相对于父元素宽度/高度的比例; - `cover` 将图片缩放至完全覆盖整个区域,可能会裁剪部分内容; - `contain` 缩放图片使其适应容器内部而不超出边界[^1]。 具体实例展示如何应用该属性: ```html <div class="example"> <!-- HTML 内容 --> </div> ``` ```css .example { width: 300px; height: 200px; background-image: url('image.jpg'); /* 设置背景图填充模式 */ background-size: cover; /* 图片按比例放大到刚好填满容器 */ } ``` #### 常见问题及解决方案 ##### 1. **背景图显示不全** 当使用固定长度定义 `background-size` 并且屏幕分辨率较大时可能出现这种情况。建议采用百分比形式或者关键字 `cover` 和 `contain` 来自动调整背景图大小[^2]。 ##### 2. **不同设备上效果差异大** 由于各终端硬件参数各异,在某些情况下即使设置了相同的 `background-size` 参数也可能呈现不同的视觉效果。此时应考虑利用媒体查询针对特定屏幕尺寸优化布局[^3]。 ##### 3. **性能影响** 对于高分辨率的大图文件,如果频繁改变其 size ,可能会影响页面加载速度。因此推荐预先压缩好所需使用的图片资源,并谨慎选择合适的 `background-size` 方式[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

铸剑先生100

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值