当前位置: 首页 > news >正文

【HarmonyOS NEXT】一次开发多端部署(以轮播图、Tab栏、列表为例,配合栅格布局与媒体查询,进行 UI 的一多开发)

关键词:一多、响应式、媒体查询、栅格布局、断点、UI

随着设备形态的逐渐增多,应用界面适配也面临着很大问题,在以往的安卓应用开发过程中,往往需要重新开发一套适用于大屏展示的应用,耗时又耗力,而鸿蒙提供响应式开发的解决方案,提供系统级的接口供开发者调用,从而使得一款应用一套代码能同时运行在不同形态的设备上,也能给用户带来很好的交互体验。

本期文章以轮播图、Tab栏、列表为例,配合栅格布局与媒体查询,进行 UI 的一多开发。

本期完整代码已提交至gitee:one2More: 【HarmonyOS NEXT】一次开发多端部署(以轮播图、Tab栏、列表为例,配合栅格布局与媒体查询,进行 UI 的一多开发)

目录

效果预览

1. 了解断点、媒体查询、栅格布局

断点

媒体查询

栅格布局

2. 封装媒体查询监听断点工具类

3. 配合媒体查询做 Swiper() 轮播图分割效果

4. 配合媒体查询做 Tab 栏 UI 展示位置变动

5. 配合栅格布局做列表展示数量控制

总结

效果预览

 普通屏

 折叠屏

 大屏

1. 了解断点、媒体查询、栅格布局

断点

鸿蒙提供断点以应用窗口宽度为切入点,将应用窗口在宽度维度上分成了几个不同的区间即不同的断点,不同设备会进入到不同的断点区间,在不同的区间下,我们可以可根据需要实现不同的页面布局效果。具体的断点对应的设备尺寸如下所示。

断点名称取值范围(vp)
xs[0, 320)
sm[320, 600)
md[600, 840)
lg[840, +∞)

媒体查询

媒体查询支持监听窗口宽度、横竖屏、深浅色、设备类型等多种媒体特征,当媒体特征发生改变时同步调整页面布局。我们可以借助媒体查询能力,监听断点的变化。

栅格布局

栅格组件默认提供xs、sm、md、lg四个断点,除了默认的四个断点,还支持启用 xl 和 xxl 两个额外的断点,我们只需要在 GridRow() 组件的 breakpoints 属性中依次设置对应断点的尺寸,可自行对断点设备的尺寸进行设置从而满足自己尺寸的业务需求,当然还是更推荐使用默认的断点尺,如果使用到媒体查询,和自定义尺寸保持一致即可。

breakpoints 数组中最大可写 5 个尺寸,对应 6 个断点范围,且断点值后面必须加上vp单位。

reference 属性代表 GridRow 宽度变化随屏幕变化,还是随当前局部区域尺寸变化(因为在实际场景中,存在应用窗口尺寸不变但是局部区域尺寸发生了变化的情况,栅格组件支持以自身宽度为参照物响应断点变化具有更大的灵活性。)

栅格布局详细介绍请参考:文档中心

示例代码:

@Entry
@Component
struct GridRowSample1 {@State private currentBreakpoint: string = 'unknown'build() {// 修改断点的取值范围同时启用更多断点,注意,修改的断点值后面必须加上vp单位。GridRow({breakpoints: {value: ['600vp', '700vp', '800vp', '900vp', '1000vp'],reference: BreakpointsReference.WindowSize}}) {GridCol({span:{xs: 12, sm: 12, md: 12, lg:12, xl: 12, xxl:12}}) {Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {Text(this.currentBreakpoint).fontSize(50).fontWeight(FontWeight.Medium)}}}.onBreakpointChange((currentBreakpoint: string) => {this.currentBreakpoint = currentBreakpoint})}
}

2. 封装媒体查询监听断点工具类

给我们的业务封装媒体查询监听断点工具类,以便后续使用,在首页生命周期过程中进行调用初始化,利用 LocalStorage 或 AppStorage 保存当前屏幕断点的名称,在应用的任意页面内通过 StorageProp 获取并动态观察屏幕设备形态状态的变化从而更新页面 UI 的展示效果,如折叠屏形态下窄屏变宽屏的使用场景,这时的断点会由 sm 变为 md。

如下代码,监听了 sm、md、lg 三种设备形态,当设备形态变化,会重新写入 storage 数据,配合状态变量即可动态更新 UI

import mediaQuery from '@ohos.mediaquery';@Observed
export class MediaWatching {private sm: string = '(width<600vp)'private md: string = "(600vp<=width<840vp)"private lg: string = "(840vp<=width)"private type: 'sm' | 'md' | 'lg' = 'sm'init() {console.log("luvi > mediaQueryResult change " + this.type)// 小尺寸屏const smListener = mediaQuery.matchMediaSync(this.sm)smListener.on('change', (mediaQueryResult) => {this.onPortrait(mediaQueryResult)})// 中等尺寸屏const mdListener = mediaQuery.matchMediaSync(this.md)mdListener.on('change', (mediaQueryResult) => {this.onPortrait(mediaQueryResult)})// 大尺寸屏const lgListener = mediaQuery.matchMediaSync(this.lg)lgListener.on('change', (mediaQueryResult) => {this.onPortrait(mediaQueryResult)})}onPortrait(mediaQueryResult: mediaQuery.MediaQueryResult) {console.log("luvi > mediaQueryResult " + JSON.stringify(mediaQueryResult))if (mediaQueryResult.matches) {switch (mediaQueryResult.media as string) {case this.sm:this.type = 'sm'breakcase this.md:this.type = 'md'breakcase this.lg:this.type = 'lg'breakdefault:break}console.log("luvi > mediaQueryResult change " + this.type)AppStorage.setOrCreate("currentMediaType", this.type)}}
}

3. 配合媒体查询做 Swiper() 轮播图分割效果

在上一步的媒体查询封装及初始化后,屏幕设备形态变化后的名称会保存在 AppStorage 中,所以我们在自定义组件中可及时获取存入的 currentMediaType ,配合 Swiper 相关接口,使用 .displayCount() 设置 Swiper 视窗内元素显示个数达到分割效果。

@Component
export struct MySwiper {swiperList: number[] = [1, 2, 3, 4, 5]// 获取当前设备断点形态@StorageProp("currentMediaType") currentMediaType: 'sm' | 'md' | 'lg' = 'sm'build() {Column() {Swiper() {ForEach(this.swiperList, (item: number, idx: number) => {Row() {Text(`图片${item}`).textAlign(TextAlign.Center).width("100%")}.borderRadius(10).width("100%").height(250).backgroundColor(idx % 2 == 0 ? "#ddd" : "#ffb0b0b0")})}.itemSpace(10)// 根据断点设置分割个数// sm 小屏形态只展示 1 个,其他形态展示 2 个.displayCount(this.currentMediaType == "sm" ? 1 : 2).autoPlay(true).borderRadius(10).clip(true)}}
}

4. 配合媒体查询做 Tab 栏 UI 展示位置变动

Tab 栏位置的变化与轮播图分栏同理,配合 storage 状态变量获取设备形态,对不同设备形态更改 Tab 栏标签的排列方向即可。

详细 Tab 代码可参考 gitee 源代码

// 获取当前设备断点形态
@StorageProp("currentMediaType") currentMediaType: 'sm' | 'md' | 'lg' = 'sm'Tabs({ barPosition: BarPosition.End }) {TabContent() {// 标签页...}TabContent() {// 标签页...}TabContent() {// 标签页...}}// 对不同设备形态设置不同排列方向.vertical(this.currentMediaType == 'sm' || this.currentMediaType == 'md' ? false : true)

5. 配合栅格布局做列表展示数量控制

栅格布局拥有独立的断点能力,不依赖与媒体查询接口,所以直接使用栅格布局的特性进行开发即可。

栅格布局主要由行和列组成,每一行可以分为若干列,在不同断点状态下展示不同数量的列数,根据这一特性,即可制作成在小屏幕上展示一列文本,在大屏幕上展示两列甚至多列文本。

所以我们可以直接对 GridRow 设置对应断点时展示的 GridCol 个数即可,无需对 GridCol 设置额外参数

GridRow({columns: {xs: 1, // 超小屏幕 1 列(如手表)sm: 1, // 小屏幕 1 列md: 2, // 中等屏幕 2 列lg: 3  // 大屏幕 3 列},gutter: 15 // gutter 表示各元素直接间隙尺寸}) {ForEach(this.dataList, (item: number, idx: number) => {GridCol() {Row() {Text(`列表${item}`).textAlign(TextAlign.Center).width("100%")}.borderRadius(10).width("100%").height(130).backgroundColor("#eee")}})}

总结

栅格布局拥有独立的断点能力,不依赖与媒体查询接口,所以直接使用栅格布局的特性进行开发即可。

轮播图的分割效果与 Tab 栏的排列方式变化,同样可使用栅格布局进行实现,不用依赖媒体查询接口,因为栅格布局的 GridRow 组件有 onBreakpointChange 断点变化回调,可直接返回当组件宽度所在的断点区间。

GridRow(){...
}
.onBreakpointChange((bp: string) => {// 此处回调打印 xs / sm / md ...
})

相关文章:

【HarmonyOS NEXT】一次开发多端部署(以轮播图、Tab栏、列表为例,配合栅格布局与媒体查询,进行 UI 的一多开发)

关键词&#xff1a;一多、响应式、媒体查询、栅格布局、断点、UI 随着设备形态的逐渐增多&#xff0c;应用界面适配也面临着很大问题&#xff0c;在以往的安卓应用开发过程中&#xff0c;往往需要重新开发一套适用于大屏展示的应用&#xff0c;耗时又耗力&#xff0c;而鸿蒙提供…...

ubontu--cuDNN安装

1. 下载 cuDNN https://developer.nvidia.com/cudnn 2. 拷贝到服务器/home/<username>文件夹下 解压缩到当前文件夹&#xff1a; tar -xvf cudnn-linux-x86_64-9.5.1.17_cuda11-archive.tar.xz复制头文件和库文件到cuda安装目录/usr/local/cuda/ sudo cp /home/usern…...

高项 - 项目范围管理

个人总结&#xff0c;仅供参考&#xff0c;欢迎加好友一起讨论 博文更新参考时间点&#xff1a;2024-12 高项 - 章节与知识点汇总&#xff1a;点击跳转 文章目录 高项 - 项目范围管理范围管理ITO规划监控 管理基础产品范围与项目范围管理新实践 5大过程组与范围管理过程概述裁…...

如何获取PostgreSQL慢查询?从小白到高手的实战指南

数据库优化是性能调优的核心&#xff0c;而慢查询则是性能瓶颈的罪魁祸首。如何找到慢查询并优化它们&#xff0c;是每个开发者和DBA都必须掌握的技能。 今天&#xff0c;我们就来聊聊如何在PostgreSQL中快速获取慢查询日志&#xff0c;并结合不同场景进行分析优化。本文风格参…...

golang分布式缓存项目 Day4 一致性哈希

注&#xff1a;该项目原作者&#xff1a;https://geektutu.com/post/geecache-day1.html。本文旨在记录本人做该项目时的一些疑惑解答以及部分的测试样例以便于本人复习 为什么使用一致性哈希 我该访问谁 对于分布式缓存来说&#xff0c;当一个节点接收到请求&#xff0c;如…...

ARM 汇编指令

blr指令的基本概念和用途 在 ARM64 汇编中&#xff0c;blr是 “Branch with Link to Register” 的缩写。它是一种分支指令&#xff0c;主要用于跳转到一个由寄存器指定的地址&#xff0c;并将返回地址保存到链接寄存器&#xff08;Link Register&#xff0c;LR&#xff09;中。…...

打造个性化体验:在Axure中创建你的专属组件库

打造个性化体验&#xff1a;在Axure中创建你的专属组件库 在数字产品设计的浪潮中&#xff0c;效率和一致性是设计团队追求的两大圣杯。 随着项目的不断扩展&#xff0c;重复性的工作逐渐增多&#xff0c;设计师们开始寻找能够提高工作效率、保持设计一致性的解决方案。 而 …...

如何用WordPress和Shopify提升SEO表现?

选择合适的建站程序对于SEO优化非常重要。目前&#xff0c;WordPress和Shopify是两种备受推崇的建站平台&#xff0c;各有优势。 WordPress最大的优点是灵活性。它支持大量SEO插件&#xff0c;帮助你调整元标签、生成站点地图、优化内容结构等。这些功能让你能够轻松地提升网站…...

不泄密的安全远程控制软件需要哪些技术

在数字化浪潮中&#xff0c;远程控制软件已不再是简单的辅助工具&#xff0c;而是成为企业运作和日常工作中不可或缺的一部分。随着远程办公模式的广泛采纳&#xff0c;这些软件提供了一种既安全又高效的途径来管理和访问远端系统。无论是在家办公、技术支持还是远程教育&#…...

rust高级特征

文章目录 不安全的rust解引用裸指针裸指针与引用和智能指针的区别裸指针使用解引用运算符 *&#xff0c;这需要一个 unsafe 块调用不安全函数或方法在不安全的代码之上构建一个安全的抽象层 使用 extern 函数调用外部代码rust调用C语言函数rust接口被C语言程序调用 访问或修改可…...

STM32F407简单驱动步进电机(标准库)

配置 单片机型号&#xff1a;STM32F104ZGT6 步进电机&#xff1a;YK28HB40-01A 驱动器&#xff1a;YKD2204M-Plus 接线方式&#xff1a; pu&#xff1a;接对应的产生PWM的引脚&#xff0c;这里接PF9&#xff0c;对应TIM14_CH1通道&#xff01; pu-&#xff1a;接单片机的G…...

使用热冻结数据层生命周期优化在 Elastic Cloud 中存储日志的成本

作者&#xff1a;来自 Elastic Jonathan Simon 收集数据对于可观察性和安全性至关重要&#xff0c;而确保数据能够快速搜索且获得低延迟结果对于有效管理和保护应用程序和基础设施至关重要。但是&#xff0c;存储所有这些数据会产生持续的存储成本&#xff0c;这为节省成本创造…...

LeetCode131. 分割回文串(2024冬季每日一题 4)

给你一个字符串 s&#xff0c;请你将 s 分割成一些子串&#xff0c;使每个子串都是 回文串 。返回 s 所有可能的分割方案。 示例 1&#xff1a; 输入&#xff1a;s “aab” 输出&#xff1a;[[“a”,“a”,“b”],[“aa”,“b”]] 示例 2&#xff1a; 输入&#xff1a;s “a…...

万字长文解读深度学习——训练(DeepSpeed、Accelerate)、优化(蒸馏、剪枝、量化)、部署细节

&#x1f33a;历史文章列表&#x1f33a; 深度学习——优化算法、激活函数、归一化、正则化深度学习——权重初始化、评估指标、梯度消失和梯度爆炸深度学习——前向传播与反向传播、神经网络&#xff08;前馈神经网络与反馈神经网络&#xff09;、常见算法概要汇总万字长文解读…...

STM32—独立看门狗(IWDG)和窗口看门狗(WWDG)

概述&#xff1a; WDG(Watchdog) 看门狗&#xff0c;看门狗可以监控程序的运行状态&#xff0c;当程序因为设计漏洞、硬件故障、电磁干扰等原因&#xff0c;出现卡死或跑飞现象时&#xff0c;看门狗能计时复位程序&#xff0c;避免程序陷入长时间的罢工状态&#xff0c;保证系…...

ks8 本地化部署 F5-TTS

huggingface上有一个demo可以打开就能玩 https://huggingface.co/spaces/mrfakename/E2-F5-TTS 上传了一段懂王的演讲片段&#xff0c;然后在 generate text框内填了点古诗词&#xff0c;生成后这语气这效果&#xff0c;离真懂王就差一个手风琴了。 F5-TTS 项目地址&#xf…...

Web组态大屏可视化编辑器

1、零代码、一键构建、一键下载 用户只需通过拖拉拽操作&#xff0c;即可在画布上添加、调整和排列各种设备组件、图表和控件。零代码拖拽方式让用户能够实时预览界面效果&#xff0c;直观地观察布局、样式和数据的变化。 2、实时展示&#xff0c;自动化连接数据&#xff0c;用…...

【comfyui教程】让模特换衣服,comfyui一键搞定!

前言 一键穿上别人的衣服&#xff1f;揭秘ComfyUI模特换装工作流&#xff01; 你有没有想过&#xff0c;某天早晨你起床后&#xff0c;只需轻轻一点&#xff0c;就能穿上明星昨晚在红毯上的华丽礼服&#xff1f;这种听起来像是科幻电影的情节&#xff0c;如今通过ComfyUI模特…...

数据湖与数据仓库的区别

数据湖与数据仓库是两种不同的数据存储和管理方式&#xff0c;它们在多个方面存在显著的区别。以下是对数据湖与数据仓库区别的详细阐述&#xff1a; 一、数据存储方式 数据仓库 通常采用预定义的模式和结构来存储数据。数据在存储前通常经过清洗、转换和整合等处理&#xff0…...

golang分布式缓存项目 Day6 防止缓存击穿

该项目原作者&#xff1a;https://github.com/geektutu/7days-golang。本文旨在记录本人做该项目时的一些疑惑解答以及部分的测试样例以便于本人复习。 1 缓存雪崩、缓存击穿与缓存穿透 概念解析&#xff1a; 缓存雪崩&#xff1a;缓存在同一时刻全部失效&#xff0c;造成瞬…...

第25节 Node.js 断言测试

Node.js的assert模块主要用于编写程序的单元测试时使用&#xff0c;通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试&#xff0c;通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...

Mac软件卸载指南,简单易懂!

刚和Adobe分手&#xff0c;它却总在Library里给你写"回忆录"&#xff1f;卸载的Final Cut Pro像电子幽灵般阴魂不散&#xff1f;总是会有残留文件&#xff0c;别慌&#xff01;这份Mac软件卸载指南&#xff0c;将用最硬核的方式教你"数字分手术"&#xff0…...

k8s业务程序联调工具-KtConnect

概述 原理 工具作用是建立了一个从本地到集群的单向VPN&#xff0c;根据VPN原理&#xff0c;打通两个内网必然需要借助一个公共中继节点&#xff0c;ktconnect工具巧妙的利用k8s原生的portforward能力&#xff0c;简化了建立连接的过程&#xff0c;apiserver间接起到了中继节…...

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...

优选算法第十二讲:队列 + 宽搜 优先级队列

优选算法第十二讲&#xff1a;队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!

简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求&#xff0c;并检查收到的响应。它以以下模式之一…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)

本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...

深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用

文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么&#xff1f;1.1.2 感知机的工作原理 1.2 感知机的简单应用&#xff1a;基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...

PHP 8.5 即将发布:管道操作符、强力调试

前不久&#xff0c;PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5&#xff01;作为 PHP 语言的又一次重要迭代&#xff0c;PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是&#xff0c;借助强大的本地开发环境 ServBay&am…...