0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

鸿蒙跨端实践-布局方案介绍

京东云 来源:京东科技 刘宁 作者:京东科技 刘宁 2024-09-18 10:26 次阅读

作者:京东科技 刘宁

一、前言

动态化使用 jue 语言(开发风格与 Vue 一致)开发,对于视图的布局采用了标准的Flex 布局方式。对于列表类视图,动态化提供了、、、等标签,将子视图的布局管理封装到标签中实现,业务只需要针对标签简单地设置相关属性,即可实现列表类布局,大幅提升研发效率。同时动态化也支持绝对布局以及控制视图的显示和隐藏等功能,使之能胜任绝大多数业务布局场景。

在京东金融App使用动态化方案适配鸿蒙系统的过程中发现,鸿蒙提供的Flex布局和W3C标准的Flex布局,在一些常用的默认属性上表现不一致。导致原本在AndroidiOS和web端显示正确的UI布局在鸿蒙端显示错乱。经与鸿蒙的工程师沟通,华为出于多方面的考虑,并没有调整的计划。故而决定废弃鸿蒙提供的布局方式,使用标准的 Flex 布局,引入yoga布局库(由 FaceBook 提供一个开源的跨平台的布局引擎),yoga库的功能是解析视图的 CSS 设置,获取视图的位置(x,y)和尺寸(width,height),直接设置给视图,确保视图的正确显示。

下面详细介绍一下鸿蒙业务在实际开发中高频使用的布局方式,这些布局方式可以涵盖95%以上的业务布局场景。

二、Flex布局

在动态化上,视图默认使用的就是flex布局方式(相当于默认设置了 display:flex;)。

1. 概念

容器(container):是指开启了flex布局的视图

项目(item):是指容器的子视图

容器(container)有几个重要的概念

主轴:item在container上的排列方向,主轴开始的位置叫 main start, 主轴结束的位置叫 main end;item在主轴上占据的尺寸叫 main size

交叉轴:与主轴垂直的方向;交叉轴开始的位置叫 cross start ,交叉轴结束的位置叫 cross end;item 在交叉轴上占据的尺寸叫 cross size

2. 容器(container)的常用属性

2.1 flex-direction

设置主轴方向,默认值是column(以下所说的默认都是指在动态化上的默认设置)。大部分设置看效果图已经很清晰,故不做过多解释。

flex-direction: row | row-reverse | column | column-reverse;

不同主轴的显示效果:

wKgaombqOi6AelE2AAIjZhQBs6c588.png

以下是假设主轴是row的情况下,介绍其他属性

2.2 flex-wrap

items在主轴上一行显示不下的情况下的折行方式,默认值是nowrap。

flex-wrap: nowrap | wrap | wrap-reverse;

不同 flex-wrap 的显示效果:

wKgZombqOi-AL29bAAGwUUF6gOs160.png

2.3 flex-flow

这是flex-direction和flex-wrap的简写方式,默认值是 column nowrap 。

flex-flow:column nowrap;

2.4 justify-content

定义item在主轴上的对齐方式,默认值是 flex-start 。

justify-content: flex-start | center | space-between | space-around | space-evenly | flex-end;

不同 justify-content 的显示效果:

wKgaombqOjCAHfLvAAKuqOhlkpE232.png

2.5 align-items

定义item在交叉轴上的对齐方式,默认是stretch。

align-items: flex-start |  center | flex-end  | stretch;

不同 align-items 的显示效果:

wKgZombqOjaABkGOAAH7-PDwyk8662.png

2.6 align-content

定义多根主轴在在交叉轴上的对齐方式(单条主轴情况下这个属性不生效)。

align-content: flex-start | flex-end | center | space-between | space-around | stretch;

这个刚接触的同学不好理解,什么是主轴的对齐方法?拿 stretch 举个例子


< text class="item" style="align-self: flex-end;" >1< /text > < text class="item" >2< /text > < text class="item" >3< /text > < text class="item" >4< /text > < text class="item" >5< /text > < text class="item" >6< /text > < text class="item" style="align-self: flex-end;" >7< /text >

UI显示效果如下:

wKgaombqOjeABAiYAAC4SFQEcBA569.png

蓝色为 container,主轴为 row(flex-direction: row;),支持折行(flex-wrap: wrap;),多行主轴的对齐方式为 stretch(align-content: stretch;),此例中有两条主轴,因此两条主轴的高将充满 container 的高;

第一条主轴中包含视图 1,2,3,4,5。第二条主轴包含视图 6,7。单条主轴的在竖直方向上的对齐方式为从上到下(align-items: flex-start;),而 1 改变了所在主轴的交叉轴方向的对齐方式为从下到上(align-self: flex-end),因此1底部对齐,2,3,4,5顶部对齐。 6,7 同理。

3.项目(item)常用属性

3.1 flex-grow

item在container中的主轴方向上的剩余空间中占据的分配比例系数(默认值为0,即不放大)。初次听起来不理解,看个例子就清楚了:


UI效果如下:

wKgZombqOjeALGRJAABaINQPxRo214.png

由于 item1 宽度为100px,item2 宽度为 50px, container在主轴剩余空间为300-100-50 = 150px;根据flex-grow 的设置,item1占1/3,为50px;item2占2/3,为100px;故最终 item1 与 item2 平分了主轴空间。

3.2 flex-shrink

item在container中的主轴方向上的缩小系数,默认值为0,即空间不够,也不缩小。这个属性仅在container无法承载item的情况下才生效。举个例子:


由于item1与item2的宽度一致,item1压缩的比例为item1的2倍,因此最终item1的尺寸是item的2倍。UI效果如下:

wKgaombqOjiAFgMiAABXJlt5GWk225.png

3.3 flex-basis

container在分配多余空间之前,item在主轴方向上占据的空间,默认值是auto,即本身默认的大小。举个例子:


由于item1宽度为150px;flex-basis默认为auto,因此默认为150px; item2宽度为150px,但flex-basis为50px,因此在计算所占空间时按50px算,这样在container的主轴上的剩余空间为 300 - 150 - 50 = 100px;item1和item2的flex-grow都为1,因此,各站剩余空间的1/2。因此item1的宽为150+50=200px;item2为50+50=100px;UI效果如下:

wKgZombqOjmAY7sTAABc0qTvGrE823.png

3.4 flex

这是一个复合属性,是flex-grow、flex-shrink 、flex-basis的简写形式。

flex: none | [ < 'flex-grow' > < 'flex-shrink' > < 'flex-basis' > ]

flex:1 等价于 flex: 1 1 auto; flex:none 等价于 flex : 0 0 auto;

注意:在使用的时候经常习惯性的使用 flex:1;很多时候大家想要的仅仅是 flex-grow:1;如非必要,尽量不要写无用约束。

3.4 align-self

item在交叉轴上的布局方式由container的align-items属性设置,如果某个item想使用别的对齐方式,可以给item设置align-self,就会覆盖container上的设置。默认值为auto,表示按照container的align-items样式,如果没有父元素,则用stretch。

align-self: auto | flex-start | flex-end | center  | stretch;

三、列表类布局

对于列表布局,动态化提供了、、、、、等标签,对于多页面管理提供、等标签。业务仅通过修改标签属性,即可实现子视图在列表内以不同的布局方式显示。

以下是列表在京东金融中的几个具体使用场景。

wKgaombqOjqAPHAwAA8Vls3KnHU491.png

四、绝对布局

对于要脱离视图文档流,不受兄弟视图布局影响,固定显示于某个指定位置的子视图,可用绝对布局,比如悬浮图标等。

1.position: absolute;

.item {
    position: absolute;
    right:10px;
    bottom:20px;
    width:50px;
    height:50px;
 }

绝对定位是相对于父视图的,使用left、right、top、bottom、width和height来设置。

五、视图的显示和隐藏控制

在开发过冲中,经常会用让视图显示或者隐藏的需求。在动态化上提供如下几种方式来实现,可根据具体的使用场景选择使用哪一种。

1. v-if = true | false


这种隐藏方式最彻底,会销毁视图,不占据任何空间,后面如果再需要显示,则元素会重新创建。这种显示/隐藏元素比较彻底,会带来的内存的开辟和回收,一般用在只显示某一种具体元素的场景下使用。

2. display : flex | none;

这种隐藏方式,不会销毁元素,仍存在于HTML文档中,仍可通过JavaScript访问和操作,但元素会从布局上移除,元素不占据任何空间,不能参与用户交互事件。

3. v-show=true | false ;

在动态化上会被解析为display:flex | none;

4. visibility : visible | hidden;

这种隐藏方式,只是从视觉上移除,仍然参与页面布局,保留元素的位置,无法参与用户交互。

5. opacity : 0 | 1

这种方式是设置视图的透明度,在透明度为0时,完全隐藏,视图仍参与页面布局,保留元素位置,在 Web、Android 和Harmony端仍可参与用户交互,但在 iOS 端只有当透明度大于0.1时可以。这个一般用作视图显示或者消失的过度动画。

6. overflow: hidden | visible

规定视图超出父视图边界时如何处理。在Harmony/iOS/Web 端默认值为visible,即超出可见,Android端默认值为hidden,超出不可见。如果设置了 visible ,如果视图本身添加了事件,对于超出父视图的部分,Harmony/Android/Web仍可响应事件,在 iOS 端无法响应事件。

多说一句:动态化作为一个跨端框架,会最大限度的抹平各端差异,但在有些系统特性上,还是会保持各端的默认实现。业务在使用时,可根据具体情况,具体处理。

六、布局问题分析

动态化在京东金融 App 里已经大范围使用,截止到 2024 年 8 月 26 日已有200+ 页面,200+卡片使用动态化技术开发。在这个过程中与各业务一起解决了很多布局相关的问题。选择几个有共性的问题分享给大家。

1. 为什么没有给item设置宽,item也没有子视图,但item却有宽呢?

因为在动态化上视图的主轴默认是column,align-items默认是stretch,因此item会填充父容器。

2. 为什么给item设置了宽,item显示的宽却是别的值?

这个情况就要具体分析了,如果你在设置了宽的情况下,还设置了flex:1;或者flex-grow:1;再或者flex-shrink等,item可能会被拉伸或者压缩,导致宽度变化。也有可能其他item的缩放级别更高,优先满足其他item的显示,当前item的尺寸也有可能被压缩。

3. item既可以从container的设置中获取尺寸,也可以被子item撑开获取尺寸,也可以自己设置尺寸,还可以被拉伸或者压缩。那item的尺寸最终是由谁来决定呢?

首先假设主轴为 column。container的align-items默认是stretch,因此item会填充父容器。但是如果item自身设置了宽,则会覆盖stretch。如果item的align-self不是stretch,本身也没有设置宽,但子视图有宽,可以被子视图撑开。如果自身设置了宽,则不受子视图影响。

在主轴方向上如果item 本身没有设置高,但子视图有高,则可以子视图撑开。如果自身设置了高,就不受子视图的影响。如果自身设置了 flex-grow:1则会填充父视图,同样如果设置了 flex-shrink:1,空间不足则被压缩,都会覆盖自身设置的高。

最后:max-width 和 max-height 优先级最高,如果触发边界条件,就会生效,从而覆盖其他设置。

4. 如何让n个item按照比例占据container的主轴空间?

对于这类比例问题,可设置所有item 的flex-basis 为 0,把自身空间全部收回,通过 flex-grow 分配对应比例即可。

5. 对于一个复杂的视图,我该如何下手?

其实越是复杂的视图实现的方式就越多,没有固定的、标准的实现方式。下面说一下我的一点看法,我将视图分为以下几种场景:

1.如果视图自身知道具体的宽高,那就直接设置,这是效率最高的方式。

2.如果视图自身不知道宽高,但是父视图有固定的尺寸,想办法从父视图获取。

3.如果视图自身不知道宽高,但子视图有宽高,则可以靠子视图撑开。

4.如果必要,使用 max-width 和 max-height 做最高层级的条件约束。

其他的情况一般都是以上四种情况的组合。只要理清视图间约束条件,排除约束矛盾点,确定优先级。先建立清晰的布局思路,明确视图的尺寸来源,按照既定思路布局,不写无效约束,一切就清晰自然。

七、写在最后

动态化是一个涉及JavaScript、iOS、Android、Harmony、Java、Vue、Node、Webpack等众多领域的综合解决方案,我们有各个领域优秀的小伙伴共同前行,大家如果想深入了解某个领域的具体实现,可以随时留言交流~!

审核编辑 黄宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • FLEX
    +关注

    关注

    0

    文章

    46

    浏览量

    15215
  • 鸿蒙
    +关注

    关注

    57

    文章

    2339

    浏览量

    42805
收藏 人收藏

    评论

    相关推荐

    鸿蒙实践-JS虚拟机架构实现

    在Roma方案中,JS虚拟机是框架的核心,负责执行动态化的JS代码。在Android平台采用了基于V8的J2V8,iOS平台则使用了系统自带的JSCore,而在HarmonyOS中,由于业界无
    的头像 发表于 09-30 14:42 2402次阅读
    <b class='flag-5'>鸿蒙</b><b class='flag-5'>跨</b><b class='flag-5'>端</b><b class='flag-5'>实践</b>-JS虚拟机架构实现

    揭秘动态化框架在鸿蒙系统下的高性能解决方案

    平台解决方案。 在研发团队使用后可大幅降低研发人力成本;为业务提供实时触达、A/B触达等能力以提升业务投放效率;同时保障了C用户优秀的用户体验。 一、动态化框架原理
    的头像 发表于 10-08 13:46 779次阅读
    揭秘动态化<b class='flag-5'>跨</b><b class='flag-5'>端</b>框架在<b class='flag-5'>鸿蒙</b>系统下的高性能解决<b class='flag-5'>方案</b>

    最佳天线实践布局指南以及天线调试程序

    有限的硬币型电池)获得的无线射程主要取决于天线的设计、塑料外壳以及良好的PCB布局。对于芯片和电源相同但布局和天线设计实践不同的系统,它们的RF(射频)范围变化超过50%也是正常的。本应用笔记
    发表于 05-21 08:51

    基于react-app配置移动自适应—淘宝弹性布局方案

    基于react-app配置移动自适应—淘宝弹性布局方案lib-flexible和postcss-px2rem实践(750px设计稿)
    发表于 06-17 17:18

    如何理解鸿蒙OS是设备的?

    谁能帮忙解释鸿蒙OS是怎样实现平台的?
    发表于 09-08 18:17

    鸿蒙介绍

    这份资料主要是对鸿蒙概念的扫盲,这里介绍鸿蒙的应用场景和技术框架,同时也有1000+页,非常详细的入门手册。这份资料具体的内容有:HarmonyOS快速入门手册2.0通用设计基础HarmonyOS入门文档
    发表于 11-24 10:49

    鸿蒙生态-2022HDC鸿蒙应用与原子化服务全新技术呈现

    基础的ArkTS语言介绍到高阶分布式设备应用开发等一系列官方视频课程,以及配套的开发文档、SDK、API、示范代码案例等。开发者通过学习本系列课程,参加考试符合标准,还可以获得获得官方鸿蒙证书与能力认证
    发表于 11-02 16:32

    鸿蒙应用ui布局

    请问,在用java开发鸿蒙应用布局UI时,怎么才能全屏布局(不显示labelb标题)
    发表于 09-20 22:09

    DC-DC降压转换器电路布局与设计和实践

    了解DC-DC降压转换器电路的最佳布局规范。在实现DC-DC降压转换器时,电路布局与设计同样重要。布局不良会严重降低设计效果。本文将介绍一些最佳布局
    的头像 发表于 07-11 16:46 1.2w次阅读
    DC-DC降压转换器电路<b class='flag-5'>布局</b>与设计和<b class='flag-5'>实践</b>

    鸿蒙强势布局2021 库克对苹果做出战略布局

    随着华为对鸿蒙系统的进一步战略布局,苹果却也作出了战略布局,看似是在阻挡鸿蒙的发展。
    的头像 发表于 01-20 11:24 1381次阅读
    <b class='flag-5'>鸿蒙</b>强势<b class='flag-5'>布局</b>2021 库克对苹果做出战略<b class='flag-5'>布局</b>

    HarmonyOS分布式算力技术介绍

    功能上无法对智能化沉浸式体验的应用提供全方位的支持,导致很多应用场景难以得到实现。 为了解决移动算力瓶颈,HarmonyOS分布式计算应运而生,给用户带来易协同、低延迟和高稳定的分布式体验。下面,我们将对
    的头像 发表于 11-17 16:34 3598次阅读
    HarmonyOS<b class='flag-5'>跨</b><b class='flag-5'>端</b>分布式算力技术<b class='flag-5'>介绍</b>

    鸿蒙应用如何唤起 QQ 安卓客户进行授权

    因为鸿蒙系统刚出不久,官方的第三方登录 SDK 还没出来,下面就介绍下在鸿蒙应用中实现 QQ 登录的方法(支持唤起 QQ 安卓客户进行授权)。
    的头像 发表于 01-04 15:01 3842次阅读

    鸿蒙开发:应用组件设备交互(流转)【迁移】

    迁移的核心任务是将应用的当前状态(包括页面控件、状态变量等)无缝迁移到另一设备,从而在新设备上无缝接续应用体验。这意味着用户在一台设备上进行的操作可以在另一台设备的相同应用中快速切换并无缝衔接。
    的头像 发表于 06-11 17:10 1232次阅读
    <b class='flag-5'>鸿蒙</b>开发:应用组件<b class='flag-5'>跨</b>设备交互(流转)【<b class='flag-5'>跨</b><b class='flag-5'>端</b>迁移】

    鸿蒙实践-长列表解决方案和性能优化

    平台都非常重要。HarmonyOS和iOS类似也提供了自己的解决方案。Roma(罗码)作为端平台,在此基础上进行了具体的实践。在实践过程中,遇到了各种问题和挑战,经历了ArkTS+C
    的头像 发表于 09-23 15:26 427次阅读
    <b class='flag-5'>鸿蒙</b><b class='flag-5'>跨</b><b class='flag-5'>端</b><b class='flag-5'>实践</b>-长列表解决<b class='flag-5'>方案</b>和性能优化

    鸿蒙原生开源库ViewPool在OpenHarmony社区正式上线

    方面的实践经验。它为鸿蒙生态的开发者和应用厂商提供了一套灵活高效的组件管理方案,有助于显著提升开发效率和应用性能。 作为一款专为Open
    的头像 发表于 12-20 14:44 137次阅读