【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 ...
})

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

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

相关文章

向日葵软件Windows系统连接苹果系统(MacOS)的无反应问题解决办法

前言 向日葵软件最近开始收费了的&#xff0c;打算收割我们。这也是没有办法的事情&#xff0c;毕竟他们的程序员也是需要吃饭的&#xff0c;我也表示理解。 所以&#xff0c;我在连接了几次发现反应很迟钝后&#xff0c;果断的买了158元的包年会员。 但是&#xff0c;在买了会…

neo4j desktop基本入门

下载安装不在赘述&#xff0c;本文只记述一些neo4j的基本入门操作 连接本地neo4j数据库 1. 点击ADD添加连接 端口一般是7687 账户名和密码忘记了&#xff0c;可以通过neo4j web&#xff08;默认为neo4jneo4j://localhost:7687/neo4j - Neo4j Browser&#xff09;重置密码 AL…

编写红绿起爆线指标(附带源码下载)

编写需求&#xff1a; 想问问有没有能标注行情起爆点的指标。 效果展示&#xff1a; 红线上&#xff0c;出现绿柱转红柱做多。 蓝线下&#xff0c;出现红柱转绿柱做空。 源码展示&#xff08;部分源码&#xff0c;完整源码需下载源码文件&#xff09;&#xff1a; IsMainIn…

ubuntu20.04 解决Pytorch默认安装CPU版本的问题

ubuntu20.04 解决Pytorch默认安装CPU版本的问题 在使用Anaconda安装支持CUDA的PyTorch版本时&#xff0c;遇到只能安装CPU版本的PyTorch是一个常见问题。这通常由于Anaconda环境配置、镜像源设置不当或版本匹配问题导致。以下是详尽的解决方案和步骤&#xff0c;以确保能够正确…

C++《继承》

在之前学习学习C类和对象时我们就初步了解到了C当中有三大特性&#xff0c;分别是封装、继承、多态&#xff0c;通过之前的学习我们已经了解了C的封装特性&#xff0c;那么接下来我们将继续学习另外的两大特性&#xff0c;在此将分为两个章节来分别讲解继承和多态。本篇就先来学…

数字孪生在智慧能源项目中的关键作用,你了解多少?

随着能源行业不断向智能化、数字化转型&#xff0c;数字孪生技术在智慧能源项目中扮演的角色愈发重要。数字孪生不仅带来了前所未有的资源优化和成本节约方式&#xff0c;还为整个能源系统的可持续运营奠定了坚实基础。那么&#xff0c;为什么数字孪生技术在智慧能源项目中如此…

Window下PHP安装最新sg11(php5.3-php8.3)

链接: https://pan.baidu.com/s/10yyqTJdwH_oQJnQtWcwIeA 提取码: qz8y 复制这段内容后打开百度网盘手机App&#xff0c;操作更方便哦 (链接失效联系L88467872) 1.下载后解压文件&#xff0c;将对应版本的ixed.xx.win文件放进php对应的ext目录下&#xff0c;如图所示 2.修改ph…

Postman上传图片如何处理

打开Postman&#xff0c;创建一个新的请求 URL: http://90.104.232.49:80/dev-api/appcommon/upload 如果有解密进入上传就在请求头添加 点击“Body”选项卡。 选择“form-data”类型。 在“KEY”列中输入文件字段的名称&#xff0c;例如file。 在“VALUE”列中&#xff0…

陪诊问诊APP开发实战:基于互联网医院系统源码的搭建详解

时下&#xff0c;开发一款功能全面、用户体验良好的陪诊问诊APP成为了医疗行业的一大热点。本文将结合互联网医院系统源码&#xff0c;详细解析陪诊问诊APP的开发过程&#xff0c;为开发者提供实用的开发方案与技术指导。 一、陪诊问诊APP的背景与功能需求 陪诊问诊APP核心目…

Leecode热题100-35.搜索插入位置

给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 示例 1: 输入: nums [1,3,5,6], target 5 输出: 2示例 2: 输入:…

Axure设计之文本编辑器制作教程

文本编辑器是一个功能强大的工具&#xff0c;允许用户在图形界面中创建和编辑文本的格式和布局&#xff0c;如字体样式、大小、颜色、对齐方式等&#xff0c;在Web端实际项目中&#xff0c;文本编辑器的使用非常频繁。以下是在Axure中模拟web端富文本编辑器&#xff0c;来制作文…

【MySQL 保姆级教学】事务的隔离级别(详细)--下(13)

事务的隔离级别 1. 如何理解事务的隔离性2. 事务隔离级别的分类3. 查看和设置事务隔离级别3.1 全局和会话隔离级别3.2 查看和设置隔离级别 4. 事务隔离级别的演示4.1 读未提交&#xff08;Read Uncommitted&#xff09;4.2 读已提交&#xff08;Read Committed&#xff09;4.3 …

大厂的 404 页面都长啥样?看看你都见过吗~~~

当我们浏览网页时&#xff0c;不小心走错路径或打开一个已被移除的页面时&#xff0c;常会遇到“404页面”。这时&#xff0c;普通网站往往只会显示冷冰冰的“404 Not Found”&#xff0c;但大厂们却能把404页面玩出花来。国内互联网大厂的404页面不仅独特&#xff0c;而且设计…

acwing算法基础02一高精度,前缀和,差分

#include <iostream> #include <vector> using namespace std;const int N 1e6 10; //模板 CABvector<int> add(vector<int> &A,vector <int> &B) {vector<int> C;int t 0; // 用来保存每位的和&#xff08;包括进位&#xff…

WebAssembly在现代Web开发中的应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 WebAssembly在现代Web开发中的应用 WebAssembly在现代Web开发中的应用 WebAssembly在现代Web开发中的应用 引言 WebAssembly 概述…

06.VSCODE:备战大项目,CMake专项配置

娇小灵活的简捷配置不过是年轻人谈情说爱的玩具&#xff0c;帝国大厦的构建&#xff0c;终归要交给CMake去母仪天下。一个没有使用 CMake 的 C 项目&#xff0c;就像未来世界里的一台相声表演&#xff0c;有了德纲却无谦&#xff0c;观众笑着遗憾。—— 语出《双城记》作者&…

从社交媒体到元宇宙:Facebook未来发展新方向

Facebook&#xff0c;作为全球最大的社交媒体平台之一&#xff0c;已经从最初的简单互动工具发展成为一个跨越多个领域的科技巨头。无论是连接人与人之间的社交纽带&#xff0c;还是利用大数据、人工智能等技术为用户提供个性化的体验&#xff0c;Facebook一直引领着社交网络的…

【go从零单排】JSON序列化和反序列化

&#x1f308;Don’t worry , just coding! 内耗与overthinking只会削弱你的精力&#xff0c;虚度你的光阴&#xff0c;每天迈出一小步&#xff0c;回头时发现已经走了很远。 &#x1f4d7;概念 在 Go 语言中&#xff0c;处理 JSON 数据主要依赖于 encoding/json 包。这个包提…

vue2.7.14 + vant + vue cli脚手架转vite启动运行问题记录

文章目录 前言方案一&#xff08;借用插件转换&#xff09;启动命令&#xff0c;转换方案一转换遇到的问题 方案二&#xff08;手动调整&#xff09;方案两者对比小结 前言 vue cli 脚手架转成vite启动 简单说说这个项目的一些底层基本结构哈&#xff0c;以及写这篇博客的目的…

Linux 常用操作指令大揭秘(下)

&#x1f31f;快来参与讨论&#x1f4ac;&#xff0c;点赞&#x1f44d;、收藏⭐、分享&#x1f4e4;&#xff0c;共创活力社区。 &#x1f31f; &#x1f6a9;用通俗易懂且不失专业性的文字&#xff0c;讲解计算机领域那些看似枯燥的知识点&#x1f6a9; 目录 &#x1f4af;…