鸿蒙:使用Stack、ContentTable、Flex等组件和布局实现一个显示界面

效果展示

38d92b82951c466c9eea6d47f2e94dd3.png

一.概述

跟随官网继续HarmonyOS学习

本篇博文实现一个食物详情页的开发Demo

通过这个开发过程学习如何使用容器组件StackFlex和基本组件ImageText构建用户自定义组件,完成图文并茂的食物介绍

二.构建Stack布局

1.食物名称

创建Stack组件,Text子组件

Stack组件为堆叠组件,可以包含一个或多个子组件,其特点是后一个子组件覆盖前一个子组件。

@Entry
@Component
struct MyComponent {build() {Stack() {Text('Tomato').fontSize(26).fontWeight(500).fontColor(Color.White)}}
}

Previewer效果: 

34e2f012a9084c7f92a12bcabc48097f.png

2.食物图片

创建Image组件,指定Image组件的url

Text组件要在Image组件上方显示,所以先声明Image组件。

图片资源放在resources下的rawfile文件夹内,引用rawfile下资源时使用$rawfile('filename')的形式,filename为 rawfile 目录下的文件相对路径。

当前$rawfile仅支持Image控件引用图片资源

@Entry
@Component
struct MyComponent {build() {Stack() {Image($rawfile('Tomato.png'))Text('Tomato').fontSize(26).fontWeight(500)}}
}

Previewer效果: 

5feee84032c84f249fee04095d06f75c.png

 

3.通过资源访问图片

除指定图片路径外,也可以使用引用 媒体资源符$r 引用资源,需要遵循resources文件夹的资源限定词的规则。

右键resources文件夹,点击New>Resource Directory,选择Resource TypeMedia(图片资源)

注:新建的Resource Directory目录只能在base目录下,但是base目录默认是有media文件的

直接把Tomato.png放入media文件夹内,就可以通过$r('app.type.name')的形式引用应用资源了

Tomato.png即为 $r('app.media.Tomato')

代码:

@Entry
@Component
struct MyComponent {build() {Stack() {Image($r('app.media.Tomato')).objectFit(ImageFit.Contain).height(357)//Image($rawfile('Tomato.png'))Text('Tomato').fontSize(26).fontWeight(500)}}
}

Previewer: 

e3297d18775a46dcae3c8fba449f2caa.png

4.Image组件objectFit属性

示例中imageobjectFit属性设置为ImageFit.Contain
即保持图片长宽比的情况下,使图片完整地显示在边界内。

ImageobjectFit默认属性是ImageFit.Cover
即在保持长宽比的情况下放大或缩小,使其填满整个显示边界。

如果要想Image填满了整个屏幕,原因如下:
    1.Image没有设置宽高。
    2.objectFit属性使用默认值ImageFit.Cover

5.设置Stack布局属性

Stack默认为居中对齐,本示例中修改为底部起始端对齐
设置Stack构造参数alignContentAlignment.BottomStart

AlignmentFontWeight一样,都是框架提供的内置枚举类型

代码:

@Entry
@Component
struct MyComponent {build() {Stack({ alignContent: Alignment.BottomStart }) {Image($r('app.media.Tomato')).objectFit(ImageFit.Contain).height(357)//Image($rawfile('Tomato.png'))Text('Tomato').fontSize(26).fontWeight(500)}}
}

Previewer:  

fe28ca1159ef4d879955177cfe18a768.png

6.调整Text组件的外边距margin

margin属性调整组件外边距

(1).margin(Length),即上、右、下、左四个边的外边距都是Length

(2).margin { top?: Length,
                    right?: Length,
                    bottom?: Length,
                    left?:Length },即分别指定四个边的边距

代码:

@Entry
@Component
struct MyComponent {build() {Stack({ alignContent: Alignment.BottomStart }) {Image($r('app.media.Tomato')).objectFit(ImageFit.Contain).height(357)Text('Tomato').fontSize(26).fontWeight(500).margin({left: 26, bottom: 17.4})}   }
}

Previewer:

8509562c2d0542e6933b8586e782ec8b.png

6.调整组件间的结构,语义化组件名称

创建页面入口组件为FoodDetail,在FoodDetail中创建Column
设置水平方向上居中对齐 alignItems(HorizontalAlign.Center)

MyComponent组件名改为FoodImageDisplay,为FoodDetail的子组件 

Column是子组件竖直排列的容器组件,本质为线性布局,所以只能设置交叉轴方向的对齐

代码:

@Component
struct FoodImageDisplay {build() {Stack({ alignContent: Alignment.BottomStart }) {Image($r('app.media.Tomato')).objectFit(ImageFit.Contain)Text('Tomato').fontSize(26).fontWeight(500).margin({ left: 26, bottom: 17.4 })}.height(357)}
}@Entry
@Component
struct FoodDetail {build() {Column() {FoodImageDisplay()}.alignItems(HorizontalAlign.Center)}
}

Previewer:

3c7653ab992b4f8a9d23fb5b12497f65.png

三.构建Flex布局

Flex:弹性布局

使用Flex弹性布局来构建食物的食物成分表,

弹性布局在本场景的优势在于可以免去多余的宽高计算,通过比例来设置不同单元格的大小,更加灵活。

1.新建ContentTable组件

新建ContentTable组件,使其成为页面入口组件FoodDetail的子组件。

代码:

@Component
struct FoodImageDisplay {build() {Stack({ alignContent: Alignment.BottomStart }) {Image($r('app.media.Tomato')).objectFit(ImageFit.Contain).height(357)Text('Tomato').fontSize(26).fontWeight(500).margin({ left: 26, bottom: 17.4 })}}
}@Component
struct ContentTable {build() {}
}@Entry
@Component
struct FoodDetail {build() {Column() {FoodImageDisplay()ContentTable()}.alignItems(HorizontalAlign.Center)}
}

Previewer:

ContentTable子组件是空的,还没填充内容,当前Previewer效果与上一节一样。

2.创建Flex组件展示Tomato两类成分

一类是热量Calories:卡路里(Calories);

一类是营养成分Nutrition,包含:蛋白质(Protein)、
                                                      脂肪(Fat)、
                                                      碳水化合物(Carbohydrates)
                                                      维生素C(VitaminC)。

先创建热量这一类
新建Flex组件,高度为280,上、右、左内边距为30,
包含三个Text子组件分别代表:类别名(Calories)
                                                  含量名称(Calories)
                                                  含量数值(17kcal)
Flex组件默认为水平排列方式。

ContentTable代码:

@Component
struct ContentTable {build() {Flex() {Text('Calories').fontSize(17.4).fontWeight(FontWeight.Bold)Text('Calories').fontSize(17.4)Text('17kcal').fontSize(17.4)}.height(280).padding({ top: 30, right: 30, left: 30 })}
}

Previewer:

501da9cb100245a6bae2d7d7d108a657.png

3.调整布局,设置各部分占比

分类名占比(layoutWeight)为1,

成分名和成分含量一共占比(layoutWeight)2。

成分名和成分含量位于同一个Flex中,成分名占据所有剩余空间flexGrow(1)。

ContentTable代码:

@Component
struct ContentTable {build() {Flex() {Text('Calories').fontSize(17.4).fontWeight(FontWeight.Bold).layoutWeight(1)Flex() {Text('Calories').fontSize(17.4).flexGrow(1)Text('17kcal').fontSize(17.4)}.layoutWeight(2)}.height(280).padding({ top: 30, right: 30, left: 30 })}
}

Previewer:

9ca5951920fa48509f45d094cc408cbe.png

4.仿照热量分类创建营养成分分类

营养成分部分(Nutrition)包含:
                  蛋白质(Protein)、
                  脂肪(Fat)、
                  碳水化合物(Carbohydrates)
                  维生素C(VitaminC)

设置外层Flex为竖直排列 FlexDirection.Column
在主轴方向(竖直方向)上等距排列 FlexAlign.SpaceBetween
在交叉轴方向(水平轴方向)上首部对齐排列 ItemAlign.Start

ContentTable代码:

@Component
struct ContentTable {build() {Flex({ direction: FlexDirection.Column,justifyContent: FlexAlign.SpaceBetween,alignItems: ItemAlign.Start }) {Flex() {Text('Calories').fontSize(17.4).fontWeight(FontWeight.Bold).layoutWeight(1)Flex() {Text('Calories').fontSize(17.4).flexGrow(1)Text('17kcal').fontSize(17.4)}.layoutWeight(2)}Flex() {Text('Nutrition').fontSize(17.4).fontWeight(FontWeight.Bold).layoutWeight(1)Flex() {Text('Protein').fontSize(17.4).flexGrow(1)Text('0.9g').fontSize(17.4)}.layoutWeight(2)}Flex() {Text(' ').fontSize(17.4).fontWeight(FontWeight.Bold).layoutWeight(1)Flex() {Text('Fat').fontSize(17.4).flexGrow(1)Text('0.2g').fontSize(17.4)}.layoutWeight(2)}Flex() {Text(' ').fontSize(17.4).fontWeight(FontWeight.Bold).layoutWeight(1)Flex() {Text('Carbohydrates').fontSize(17.4).flexGrow(1)Text('3.9g').fontSize(17.4)}.layoutWeight(2)}Flex() {Text(' ').fontSize(17.4).fontWeight(FontWeight.Bold).layoutWeight(1)Flex() {Text('vitaminC').fontSize(17.4).flexGrow(1)Text('17.8mg').fontSize(17.4)}.layoutWeight(2)}}.height(280).padding({ top: 30, right: 30, left: 30 })}
}

Previewer:

38d92b82951c466c9eea6d47f2e94dd3.png

5.优化代码

可以发现,每个成分表中的成分单元其实都是一样的UI结构

2c75982c6a0849be90ac1400fa46ee09.png

可以通过自定义@Builder函数对代码进行精简

使用自定义@Builder抽象出相同的UI结构
@Builder修饰的方法和Componentbuild方法都是为了声明一些UI渲染结构,遵循一样的ArkTS语法。

可以定义一个或者多个 @Builder修饰的方法,但Componentbuild方法必须只有一个

ContentTable内声明@Builder修饰的IngredientItem方法,用于声明分类名、成分名称和成分含量UI描述。

@Component
struct ContentTable {@Builder IngredientItem(title:string, name: string, value: string) {Flex() {Text(title).fontSize(17.4).fontWeight(FontWeight.Bold).layoutWeight(1)Flex({ alignItems: ItemAlign.Center }) {Text(name).fontSize(17.4).flexGrow(1)Text(value).fontSize(17.4)}.layoutWeight(2)}}
}

ContentTablebuild方法内调用IngredientItem接口,
需要用this去调用该Component作用域内的方法,以此来区分全局的方法调用。

@Component
struct ContentTable {......build() {Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Start }) {this.IngredientItem('Calories', 'Calories', '17kcal')this.IngredientItem('Nutrition', 'Protein', '0.9g')this.IngredientItem('', 'Fat', '0.2g')this.IngredientItem('', 'Carbohydrates', '3.9g')this.IngredientItem('', 'VitaminC', '17.8mg')}.height(280).padding({ top: 30, right: 30, left: 30 })}
}

ContentTable组件全代码如下:

@Component
struct ContentTable {@BuilderIngredientItem(title:string, name: string, value: string) {Flex() {Text(title).fontSize(17.4).fontWeight(FontWeight.Bold).layoutWeight(1)Flex() {Text(name).fontSize(17.4).flexGrow(1)Text(value).fontSize(17.4)}.layoutWeight(2)}}build() {Flex({ direction: FlexDirection.Column,justifyContent: FlexAlign.SpaceBetween,alignItems: ItemAlign.Start }) {this.IngredientItem('Calories', 'Calories', '17kcal')this.IngredientItem('Nutrition', 'Protein', '0.9g')this.IngredientItem('', 'Fat', '0.2g')this.IngredientItem('', 'Carbohydrates', '3.9g')this.IngredientItem('', 'VitaminC', '17.8mg')}.height(280).padding({ top: 30, right: 30, left: 30 })}
}

Previewer:

本小节只是优化代码,实现效果与上一小节相同

四.结束语

Stack布局Flex布局已完成食物的图文展示和营养成分表,构建出了第一个普通视图的食物详情页

下一篇博文将继续跟随官网,开发食物分类列表页,并完成食物分类列表页面和食物详情页面的跳转和数据传递。

 

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

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

相关文章

【Dubbo】Dubbo负载均衡实现解析

📫作者简介:小明java问道之路,2022年度博客之星全国TOP3,专注于后端、中间件、计算机底层、架构设计演进与稳定性建设优化,文章内容兼具广度、深度、大厂技术方案,对待技术喜欢推理加验证,就职于…

Android 13 - Media框架(14)- OpenMax(二)

这一节我们将来解析 media.codec 这个 HIDL service 究竟提供了什么服务,服务是如何启动的。 1、main 函数 我们先来看 frameworks/av/services/mediacodec/main_codecservice.cpp: int main(int argc __unused, char** argv) {strcpy(argv[0], "…

广州华锐互动VRAR:利用VR开展刑事案件公安取证培训,沉浸式体验提升实战能力

随着科技的飞速发展,虚拟现实(VR)技术为我们的生活和工作带来了前所未有的便利。近年来,VR技术在刑事案件公安取证培训中的应用逐渐显现出其独特优势。通过模拟真实的犯罪现场,VR技术为学员提供了沉浸式的体验,使他们在安全的环境…

java文件压缩加密,使用流的方式

使用net.lingala.zip4j来进行文件加密压缩。 添加依赖net.lingala.zip4j包依赖&#xff0c;这里使用的是最新的包2.11.5版本。 <dependency><groupId>net.lingala.zip4j</groupId><artifactId>zip4j</artifactId><version>${zip4j.versi…

微服务调用链路追踪

概述 本文介绍微服务调用链路追踪&#xff0c;涉及技术有&#xff1a;sleuth和zipkin。sleuth负责追踪调用链路数据&#xff0c;zipkin负责调用链路数据可视化展现。 本文的操作是在 服务网关实践 的基础上进行。 环境说明 jdk1.8 maven3.6.3 mysql8 spring cloud2021.0.8 …

【Python仿真】基于EKF的传感器融合定位

基于EKF的传感器融合定位&#xff08;Python仿真&#xff09; 简述1. 背景介绍1.1. EKF扩展卡尔曼滤波1.1.1.概念1.1.2. 扩展卡尔曼滤波的主要步骤如下&#xff1a;1.1.3. 优、缺点 1.2. 航位推算1.3. 目前航位算法的使用通常与卡尔曼滤波相结合使用2. 分段代码 2.1. 导入需要的…

wpf devexpress 添加GanttControl到项目

这个教程示范如何添加GanttControl 到你的项目使用内置GanttControl数据类。 要求 添加 Devexpress.Wpf.Gantt Nuget包到你的项目使用GanttControl. 数据模型 GanttControl携带和内置数据对象&#xff0c;可以使用创建视图模型&#xff1a; GanttTask 呈现甘特图任务 Gan…

记录将excel表无变形的弄进word里面来

之前关于这个问题记录过一篇文章&#xff1a; 将excel中的表快速复制粘贴进word中且不变形-CSDN博客 今天记录另外一种方法&#xff1a;举例表述&#xff0c;excel表如图&#xff1a; 按F12&#xff0c;出现“另存为...”对话框&#xff0c;选择“单个文件网页”&#xff0c;…

面向对象与面向过程的区别

面向对象 以对象为中心&#xff0c;把数据封装成为一个整体&#xff0c;其他数据无法直接修改它的数据&#xff0c;将问题分解成不同对象&#xff0c;然后给予对象相应的属性和行为。 面向过程 关注代码过程&#xff0c;直接一程序来处理数据&#xff0c;各模块之间有调用与…

oracle-buffer cache

段&#xff0c;区&#xff0c;块。 每当新建一个表&#xff0c;数据库会相应创建一个段。然后给这个段分配一个区。 一个区包含多个块。 区是oracle给段分配空间的最小单位。 块是oracle i\o的最小单位。 原则上&#xff0c;一个块包含多行数据。 dbf文件会被划分成一个一个…

Netty Review - 核心组件扫盲

文章目录 PreNetty Reactor 的工作架构图CodePOMServerClient Netty 重要组件taskQueue任务队列scheduleTaskQueue延时任务队列Future异步机制Bootstrap与ServerBootStrapgroup()channel()option()与childOption()ChannelPipelinebind()优雅地关闭EventLoopGroupChannleChannel…

今天遇到Windows 10里安装的Ubuntu(WSL)的缺点

随着技术的发展&#xff0c;越来越多开发者转向使用 Windows Subsystem for Linux&#xff08;WSL&#xff09;在 Windows 10 上进行开发&#xff0c;也就是说不用虚拟机&#xff0c;不用准备多一台电脑&#xff0c;只需要在Windows 10/11 里安装 WSL 就能体验 Linux 系统。因此…

邀请报名|11月24日阿里云原生 Serverless 技术实践营 深圳站

活动简介 “阿里云云原生 Serverless 技术实践营 ” 是一场以 Serverless 为主题的开发者活动&#xff0c;活动受众以关注 Serverless 技术的开发者、企业决策人、云原生领域创业者为主&#xff0c;活动形式为演讲、动手实操&#xff0c;让开发者通过一个下午的时间增进对 Ser…

how to find gcc openbug

https://gcc.gnu.org/bugzilla/query.cgi?formatadvanced

最全的接口自动化测试思路和实战:【推荐】混合测试自动化框架(关键字+数据驱动)

混合测试自动化框架(关键字数据驱动) 关键字驱动或表驱动的测试框架 这个框架需要开发数据表和关键字。这些数据表和关键字独立于执行它们的测试自动化工具&#xff0c;并可以用来“驱动&#xff02;待测应用程序和数据的测试脚本代码&#xff0c;关键字驱动测试看上去与手工测…

mount /dev/mapper/centos-root on sysroot failed处理

今天发现centos7重启开不进去系统 通过查看日志主要告警如下 修复挂载目录 xfs_repair /dev/mapper/centos-root不行加-L参数 xfs_repair -L /dev/mapper/centos-root重启 reboot

云课五分钟-0Cg++默认版本和升级-std=c++17

前篇&#xff1a; 云课五分钟-0B快速排序C示例代码-注释和编译指令 视频&#xff1a; 云课五分钟-0Cg默认版本和升级-stdc17 文本&#xff1a; 在Linux系统中&#xff0c;可以通过以下步骤升级g&#xff1a; 打开终端&#xff0c;使用root权限或者sudo权限登录。输入以下命令…

基于灰狼算法(GWO)优化的VMD参数(GWO-VMD)

代码的使用说明 基于灰狼算法优化的VMD参数 代码的原理 基于灰狼算法&#xff08;Grey Wolf Optimizer, GWO&#xff09;优化的VMD参数&#xff08;GWO-VMD&#xff09;是一种结合了GWO和VMD算法的优化方法&#xff0c;用于信号分解和特征提取。 GWO是一种基于群体智能的优化…

lv11 嵌入式开发 ARM指令集中(伪操作与混合编程) 7

目录 1 伪指令 2 伪操作 3 C和汇编的混合编程 4 ATPCS协议 1 伪指令 本身不是指令&#xff0c;编译器可以将其替换成若干条等效指令 空指令NOP 指令LDR R1, [R2] 将R2指向的内存空间中的数据读取到R1寄存器 伪指令LDR R1, 0x12345678 R1 0x12345678 LDR伪指令可以将任…

小米真无线耳机 Air 2s产品蓝牙配对ubuntu20.04 笔记本电脑

小米真无线耳机 Air 2s产品蓝牙配对ubuntu20.04 笔记本电脑 1.我的笔记本是 22款联想拯救者y9000k&#xff0c;安装了双系统&#xff0c;ubuntu20.04。 2.打开耳机&#xff0c;按压侧面按钮2秒&#xff0c;指示灯显示白色闪烁。 3.打开ubunru20.04 系统右上角wifi的位置&…