鸿蒙布局第二篇--详细介绍ArkUI中的相对布局,网格布局和轮播组件

在上一篇鸿蒙布局第一篇--详细介绍ArkUI中线性布局,层叠布局和弹性布局中,我们学习了ArkUI中线性布局,层叠布局和弹性布局的用法,了解到了这三种布局的特性以及各自都适用于哪种场景,那么这篇文章里面继续针对鸿蒙的布局组件做介绍,今天的主角是相对布局,网格布局和轮播组件

相对布局(RelativeContainer)

ArkUI的相对布局有点类似于Android里面的RelativeLayout,相对布局里面的元素通过指定父布局或者其他元素作为锚点来设置自己的位置,跟RelativeLayout一样,在相对布局中每一个元素都必须有一个属于自己的唯一id,父布局的id是" __ Container __ "

注意:这里的Container前后其实是各两条下划线,文档里面是看不出来两条,如果Container前后只输入一条下划线的话,那么针对父布局作为锚点的布局将会失效,另外,也必须注意一点的是每一个元素的id是必须设置的,如果不设置id,该元素将不会在布局中出现

下面来敲几个例子来切身体会下这个相对布局,首先在一个相对布局中的四个角上各放置一个视图,代码如下

可以看到在相对布局中设置位置是通过函数alignRules来完成的,在函数中,垂直方向可以设置top,center,bottom位置的锚点,水平方向可以设置left,middle,right位置的锚点,锚点对象则是通过anchor属性来设置,anchor就是每一个元素设置的id,而对齐方式就是通过align属性来设置,水平方向上有HorizontalAlign.StartHorizontalAlign.CenterHorizontalAlign.End这三个选项,垂直方向上有VerticalAlign.Top,VerticalAlign.Center,VerticalAlign.Bottom这三个选项,比如现在我们想让text2text1的下方,text2的左边与text1的右边对齐,让text3text4的上方,并且text3的右边与text4的左边对齐,那么可以通过更改anchoralign来实现,代码如下

只需要更改锚点对象以及对齐方式,元素的位置就发生改变了,基本上同Android里面的RelativeLayout思想差不多

网格布局(Grid/GridItem)

网格布局也是比较常用的几个布局之一,比如日历,相册之类的应用都用到了网格布局,在ArkUI中的网格布局使用Grid组件,并且Grid的子组件必须使用GridItem,接下来通过几个主要的属性来讲下如何使用网格布局

设置行列数量以及占比

网格布局里面分别使用rowsTemplate函数来设置行数以及占比,使用columnsTemplate函数来设置列数以及占比,设置方法都一样,都是在函数里面传入一个字符串,字符串类似于下面这个样子

通过空格将每个数字+fr的字符串分割开来,这串字符串代表的意义有两个,有多少个fr就代表行或者列的数量,fr前面的数字表示分割比例,下面看个例子

看到这里有个网格布局,并且将网格横向等分成四份,纵向也将网格等分成4份,但是总的数据有17个,我们运行下代码看看效果

可以看到只出现了十六个元素,第十七个元素不见了,被挡在了视图的外面,如果我们也想看到第十七个元素,就必须让网格布局滚动起来,滚动起来的方式很简单,只设置行列方向占比的其中一个,比如只保留列数和列占比设置,那么网格的主轴方向就是水平的,反之主轴方向就是垂直的,这样一来元素就会先沿着主轴方向排版,交叉轴方向元素布局如果超出Grid的大小,超出的元素就可以通过滚动来查看,比如上面这个例子,我们去掉行设置rowsTemplate看看效果

由于是去掉了行高的比例,所以给每个单项设置了120vp的高度,运行后的效果如下

可以看到如果元素在交叉轴方向超出了Grid的大小,超出部分我们就可以向上滑动屏幕看到了,同样的,我们如果只设置行高的比例,不设置列的比例,那么布局元素的交叉轴就变成了水平方向,更改下代码我们再看看实际效果

设置行间距,列间距

上述例子中可能有一点让大家感到不适,就是元素与元素之间都挤在了一起,分不清哪些区域属于某一个元素,所以通常这个时候我们就需要给元素之间设置间距了,而对于网格布局,它的间距分为行间距与列间距,分别用函数rowsGapcolumnsGap来设置,传进去的参数就代表间距大小,比如给上面的例子添加间距,代码就是这样的

增加了5vp的行间距,10vp的列间距,现在运行一遍代码后效果稍微好看一点了

设置子组件所占的行列数

现在很多app的瀑布列经常会出现某一项item的宽高要比其他item要大,比如其他item高度占了一行,这个大一点的item占了两行,那么像这个样子的场景在网格布局中如何做呢?我们可以给GridItem设置rowStartrowEnd来跨越对应的行数,设置columnStartcolumnEnd来跨越对应的列数,同样是上面的例子,我们现在想让元素6可以向下跨一行,元素10可以向右跨一行,可以这样做

代码中元素6调用了rowStart函数,传入了它本身所在的行数1,然后调用rowEnd函数,传入了它所需要跨入的行数2,同样给元素10也设置了columnStart(2)columnEnd(3),然后看下效果

正如代码中设置的一样,6跟10都跨越了自己的行数或者列数,可能细心的朋友们已经发现了,这里同时给网格布局设置了横向与纵向的比例,如果我只设置其中一个比例,那么子组件还会完成跨越吗,下面来试试看

这里将列的比例给去掉了,只剩下行的比例,那么最终元素6与10还能不能正常跨越呢,跑下看看

由于列的比例去掉了,子组件也没有设置width,所以展示的效果子组件才会变得这么窄,这个可以忽略,我们发现,元素6依然可以成功跨越行数,但是元素10就不一样了,没有跨越2列与3列,只占了第3列的格子,第2列是空着的,那么同样的,保留列的比例设置,去除行的比例,那是不是元素6也不能跨了呢,再试下

的确如此,所以我们可以得出这样的结论,网格布局的子组件如果想要横向跨越,那么必须设置列数和列占比,如果想要纵向跨越,那么必须设置行数和行占比

设置主轴方向

前面有尝试过分别只设置行比例或者列比例的时候,网格布局的主轴和交叉轴会来回切换,那么如果行列比例都不设置,那么该如何设置主轴方向呢,可以通过设置layoutDirectionmaxCount来实现,前者是确定主轴方向,有四个值分别为GridDirection.RowGridDirection.RowReverse,GridDirection.ColumnGridDirection.ColumnReverse,后者是确定主轴上的最大数量,接下来通过上面的例子分别使用这四个方向来感受下布局方向以及排版,maxCount就设置为3

GridDirection.Row

GridDirection.RowReverse

GridDirection.Column

GridDirection.ColumnReverse

轮播组件(Swiper)

ArkUI里面的这个组件我还是比较喜欢的,有了这个组件就可以更加轻松的去实现类似于banner一样的轮播图功能,想想在Android原生中如果想要去实现一个轮播图,基本都会去找三方组件,就算自己去实现也是一大段代码,Compose里面虽然使用Pager也可以很容易的去实现轮播图,但Pager组件在Compose1.4.0之前还在Accompanist库里面,必须额外去依赖进来才可以使用,而ArkUI一上来就给我们提供了Swiper这个组件,接下来就看看Swiper组件都有啥特性

布局与约束

Swiper组件当自身没有设置大小的时候,它的大小随着子组件的变化而改变,当自身设置了大小之后,所有子组件都以Swiper大小展示,下面来看两个例子

Swiper没有设置容器高度

代码中我们给第一个子组件设置了100vp的高度,后面两个组件分别设置了200vp跟150vp的高度,而Swiper是没有设置高度的,从效果图中我们发现,每个子组件的高度都以自身的高度为准

Swiper设置了自身高度

从这个例子中可以看到,当Swiper设置了容器高度之后,尽管子组件的高度都不一样,但是最终展现的效果子组件都以容器的高度来展示

自动轮播

前面说了Swiper可以实现banner一样效果,而banner是可以自动轮播的,所以Swiper该如何实现自动轮播这个功能呢?很简单,可以设置autoPlay属性,当它为true的时候,Swiper就可以实现自动轮播功能了

上述代码只是在之前的例子中多设置了一个autoPLay(true)的属性,我们这个Swiper就能够自动轮播了,效果如下

当自动轮播的时候,每一次切换的时间间隔是3秒,如果想要自己设置切换的时间间隔,可以通过设置interval属性来实现,比如将上述例子的时间间隔改成1秒,就可以这样设置

也是通过一个属性,就将Swiper的切换时间给改变了

导航点

可能大家也都发现了,当我们创建了一个Swiper组件的时候,组件会默认自带一个导航点样式,就算Swiper里面只有一个组件,导航点依然会存在,默认与Swiper底部对齐,居中显示,但有时候,我们只想要实现类似于Android中ViewPager一样的翻页的效果,不想要导航点,那么该如何去掉呢?可以去设置indicator属性,它默认为true,表示展示导航点,只要将它设置成false,导航点就没有了,我们看下面的代码

可以从效果图中看到,我们只是在上面的例子中多添加了一个indicator(false)的属性,就成功的去掉了导航点,还是很容易的,但是对于导航点来说,大家遇到的更多的情况就是去更改导航点的样式以及它的位置,而Swiper中的indicatorStyle属性就是用来更改导航点的样式以及位置的,首先可以通过top,left,bottom,right去设置导航点相对于Swiper的间距,比如现在默认是居中与底部对齐,我们想要让导航点与Swiper左边间距10vp,与顶部间距10vp,就可以这样设置

得到的效果就如图所示导航点就靠Swiper的左上位置了,而如果想要设置导航点的大小,就可以使用size去设置,比如我们想要让导航点的圆点直径大小变成30vp,就可以这样设置

这样就获得了一个直径大小为30vp的导航点,另外选中与未选中的色值,也可以通过selectedColorcolor来设置

这里将选中状态的颜色设置成了#757575,将未选中的色值颜色改成了#2e212121,得到的效果图如下

总结

这三种布局算是在日常开发中比较常用的,而且使用起来也比较简单,但尽管这样,有些细节如果不注意,依然会产生一些很困惑的问题,比如相对布局里面父布局的id,要不是我将官方文档里面的示例代码复制出来才发现原来有两个下划线,我可能还会指着模拟器上怎么都无法与父布局右边对齐的元素对隔壁同事说:快看!我找到个bug!

相关推荐
雾散声声慢5 分钟前
前端开发中怎么把链接转为二维码并展示?
前端
熊的猫6 分钟前
DOM 规范 — MutationObserver 接口
前端·javascript·chrome·webpack·前端框架·node.js·ecmascript
天农学子6 分钟前
Easyui ComboBox 数据加载完成之后过滤数据
前端·javascript·easyui
mez_Blog7 分钟前
Vue之插槽(slot)
前端·javascript·vue.js·前端框架·插槽
爱睡D小猪10 分钟前
vue文本高亮处理
前端·javascript·vue.js
开心工作室_kaic13 分钟前
ssm102“魅力”繁峙宣传网站的设计与实现+vue(论文+源码)_kaic
前端·javascript·vue.js
放逐者-保持本心,方可放逐13 分钟前
vue3 中那些常用 靠copy 的内置函数
前端·javascript·vue.js·前端框架
IT古董13 分钟前
【前端】vue 如何完全销毁一个组件
前端·javascript·vue.js
Henry_Wu00116 分钟前
从swagger直接转 vue的api
前端·javascript·vue.js
SameX25 分钟前
初识 HarmonyOS Next 的分布式管理:设备发现与认证
前端·harmonyos