HarmonyOS 鸿蒙Next应用开发基础架构搭建-多端布局之挪移布局
HarmonyOS 鸿蒙Next应用开发基础架构搭建-多端布局之挪移布局
期待HarmonyOS能在未来推出更多针对特定场景的优化功能。
关于HarmonyOS 鸿蒙Next应用开发基础架构搭建-多端布局之挪移布局的问题,您也可以访问:https://www.itying.com/category-93-b0.html 联系官网客服。
在鸿蒙(HarmonyOS)的UI设计中,“挪移布局”是一种用于响应屏幕尺寸变化的布局策略,特别是在设备方向改变或者在不同设备类型间切换时。鸿蒙系统支持多种设备形态,包括手机、平板、智能手表、车载系统和智慧屏等,因此挪移布局对于确保应用在所有设备上都有良好的适应性和一致性至关重要。
挪移布局的基本思想是在屏幕尺寸显著变化时(如屏幕宽高比变化超过200%),自动或手动调整界面元素的排列方式。
例如,一个应用在手机竖屏模式下可能采用垂直堆叠的布局(如产品图在上,内容在下),但在横屏或更大的屏幕上(如平板或智慧屏),同一应用可能会采用水平并排的布局。如下图:
手机端
大屏
可以看到,一般的电商商品页面,自上到下依次为产品图、产品规格、产品介绍和评价等,通常情况下,产品图和产品规格会占据首屏的区域,用户需要下滑才能看到商品详情。这样的页面设计如果在大屏上依然采用上下结构,那么会非常浪费屏幕空间,同时因为页面拉伸,用户需要滑动的频率会比手机端更高,不利于体验。所以在大屏上,左右结构更利于产品详情的展示,同时也更有利于用户在减少操作的情况下查看整个商品页面的内容。
如下图展示:
大屏上直接使用上下布局
实现小屏幕上下布局,大屏上左右布局,同时基于鸿蒙的一套代码来实现,有很多种实现方式。
例如可以通过GirdRow/GridCol组件,通过栅格布局和断点控制实现布局切换。也可以使用断点+判断隐藏,在不同尺寸的屏幕上,隐藏不同的UI组件来实现布局切换。
这里使用GridRow/GridCol组件,配合断点控制来实现挪移布局。栅格布局相关介绍可以看上一篇文章:鸿蒙Next基础架构搭建-多端布局之栅格布局
首先,商品详情页面内容较多,需要对布局进行分析:
- 手机端 :需要加入scroll进行页面上下滚动,scroll组件作为最外层组件包裹所有视图。
- 大屏:挪移为左右结构以后,左侧图片区域固定高度,右侧内容区域可以滚动,内容区域通过scroll组件包裹所有右侧内容视图。
这样带来的问题就是,需要根据断点动态控制内容区域和外层区域的scroll组件的滚动行为。
在上下结构时候,内容区域的scroll组件禁用滚动,外层区域的scroll组件可滚动;在左右结构的时候,外层区域的scroll组件禁用滚动,内容区域可滚动。
关键代码如图:
外层scroll滚动控制
内容区域scroll滚动控制
设置好Scroll组件以后,将相应结构,嵌入GridRow和GridCol组件中,并设置相应断点控制,小屏上 占据所有空间,大屏上两列布局。
最终效果实现如下:
小屏幕
平板
平板分屏
接下来看一下具体代码实现:
[@Entry](/user/Entry)
[@Component](/user/Component)
struct Detail {
[@State](/user/State) currentBreakpoint: string = 'unknown';
[@State](/user/State) paddingSize: number = 0;
build() {
RelativeContainer() {
Scroll(){
GridRow({
columns: {
sm: 4,
md: 4,
lg: 12
}
}) {
// 产品图区域
GridCol({span: {sm: 4, md: 4, lg: 6}}) {
// 1.产品图
Column(){
Image($r('app.media.p2')).width('100%').height('100%')
}
.width('100%')
.height('100%')
.aspectRatio(1)
}
.height(this.currentBreakpoint !== 'lg' ? 'auto' : '100%')
<span class="hljs-comment"><span class="hljs-comment">// 产品介绍区域</span></span>
GridCol({span: {sm: <span class="hljs-number"><span class="hljs-number">4</span></span>, md: <span class="hljs-number"><span class="hljs-number">4</span></span>, lg: <span class="hljs-number"><span class="hljs-number">6</span></span>}}) {
Scroll(){
Column(){
<span class="hljs-comment"><span class="hljs-comment">// 2.产品价格</span></span>
Column(){
Text(<span class="hljs-string"><span class="hljs-string">'¥11499'</span></span>)
.fontSize(<span class="hljs-number"><span class="hljs-number">22</span></span>)
.fontColor(<span class="hljs-string"><span class="hljs-string">'#cf0a2c'</span></span>)
.width(<span class="hljs-string"><span class="hljs-string">'100%'</span></span>)
.margin({top: <span class="hljs-number"><span class="hljs-number">6</span></span>})
Text(<span class="hljs-string"><span class="hljs-string">'花呗/掌上生活分期直购,最高可享12期0分期利息'</span></span>)
.fontSize(<span class="hljs-number"><span class="hljs-number">16</span></span>)
.fontColor(<span class="hljs-string"><span class="hljs-string">'#666666'</span></span>)
.width(<span class="hljs-string"><span class="hljs-string">'100%'</span></span>)
.margin({top: <span class="hljs-number"><span class="hljs-number">6</span></span>})
}
.backgroundColor(Color.White)
.borderRadius(<span class="hljs-number"><span class="hljs-number">8</span></span>)
.padding(<span class="hljs-number"><span class="hljs-number">16</span></span>)
.margin({ top: <span class="hljs-number"><span class="hljs-number">12</span></span>, left: <span class="hljs-number"><span class="hljs-number">12</span></span>, right: <span class="hljs-number"><span class="hljs-number">12</span></span>})
<span class="hljs-comment"><span class="hljs-comment">// 3.产品规格</span></span>
Column(){
Text(<span class="hljs-string"><span class="hljs-string">'HUAWEI Mate X5 12GB+256GB 幻影紫'</span></span>)
.fontSize(<span class="hljs-number"><span class="hljs-number">18</span></span>)
.width(<span class="hljs-string"><span class="hljs-string">'100%'</span></span>)
.margin({top: <span class="hljs-number"><span class="hljs-number">6</span></span>})
Text(<span class="hljs-string"><span class="hljs-string">'①夏日礼遇,限时直降活动时间6月28日00:00-7月31日23:59 ②12期0分期利息(微信小程序尚不支持,请前往APP端使用)'</span></span>)
.fontSize(<span class="hljs-number"><span class="hljs-number">16</span></span>)
.fontColor(<span class="hljs-string"><span class="hljs-string">'#cf0a2c'</span></span>)
.width(<span class="hljs-string"><span class="hljs-string">'100%'</span></span>)
.margin({top: <span class="hljs-number"><span class="hljs-number">6</span></span>})
Text(<span class="hljs-string"><span class="hljs-string">'超轻薄四曲折叠,超高清高分辨率临境双屏,超智慧灵犀通信'</span></span>)
.fontSize(<span class="hljs-number"><span class="hljs-number">14</span></span>)
.fontColor(<span class="hljs-string"><span class="hljs-string">'#666666'</span></span>)
.width(<span class="hljs-string"><span class="hljs-string">'100%'</span></span>)
.margin({top: <span class="hljs-number"><span class="hljs-number">6</span></span>})
}
.backgroundColor(Color.White)
.borderRadius(<span class="hljs-number"><span class="hljs-number">8</span></span>)
.padding(<span class="hljs-number"><span class="hljs-number">16</span></span>)
.margin({ top: <span class="hljs-number"><span class="hljs-number">12</span></span>, left: <span class="hljs-number"><span class="hljs-number">12</span></span>, right: <span class="hljs-number"><span class="hljs-number">12</span></span>})
<span class="hljs-comment"><span class="hljs-comment">// 4.产品介绍</span></span>
Column(){
Text(<span class="hljs-string"><span class="hljs-string">'产品介绍'</span></span>).fontSize(<span class="hljs-number"><span class="hljs-number">24</span></span>).margin({ top: <span class="hljs-number"><span class="hljs-number">24</span></span>, bottom: <span class="hljs-number"><span class="hljs-number">24</span></span> })
Image($r(<span class="hljs-string"><span class="hljs-string">'app.media.phone_detail_1'</span></span>)).width(<span class="hljs-string"><span class="hljs-string">'100%'</span></span>)
Image($r(<span class="hljs-string"><span class="hljs-string">'app.media.phone_detail_2'</span></span>)).width(<span class="hljs-string"><span class="hljs-string">'100%'</span></span>)
Image($r(<span class="hljs-string"><span class="hljs-string">'app.media.phone_detail_3'</span></span>)).width(<span class="hljs-string"><span class="hljs-string">'100%'</span></span>)
}
}
.width(<span class="hljs-string"><span class="hljs-string">'100%'</span></span>)
}
.width(<span class="hljs-string"><span class="hljs-string">'100%'</span></span>)
.scrollable(<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.currentBreakpoint !== <span class="hljs-string"><span class="hljs-string">'lg'</span></span> ? ScrollDirection.None : ScrollDirection.Vertical)
}
.backgroundColor(<span class="hljs-string"><span class="hljs-string">'#f1f3f5'</span></span>)
}
.onBreakpointChange((currentBreakpoint: string) => {
<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.currentBreakpoint = currentBreakpoint
})
}
.width(<span class="hljs-string"><span class="hljs-string">'100%'</span></span>)
.height(<span class="hljs-string"><span class="hljs-string">'100%'</span></span>)
.scrollable(<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.currentBreakpoint !== <span class="hljs-string"><span class="hljs-string">'lg'</span></span> ? ScrollDirection.Vertical : ScrollDirection.None)
}
.height(<span class="hljs-string"><span class="hljs-string">'100%'</span></span>)
.width(<span class="hljs-string"><span class="hljs-string">'100%'</span></span>)
}
}
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>
其他布局方式和相关文章可以查看以下文章:
HarmonyOS NEXT应用开发基础架构搭建-设计理念和目录结构
HarmonyOS NEXT应用开发基础架构搭建-路由页面权限控制
HarmonyOS NEXT应用开发基础架构搭建-多端布局之自适应布局
HarmonyOS NEXT应用开发基础架构搭建-多端布局之响应式布局
HarmonyOS NEXT应用开发基础架构搭建-多端布局之栅格布局