您的位置 首页 > 德语词汇

compositional是什么意思,compositional的意思翻译、用法 Compositional

本篇文章给大家谈谈compositional是什么意思,compositional的意思翻译、用法,以及Compositional对应的知识点,文章可能有点长,但是希望大家可以阅读完,增长自己的知识,最重要的是希望对各位有所帮助,可以解决了您的问题,不要忘了收藏本站喔。

CollectionViewLayout全详解

compositional是什么意思,compositional的意思翻译、用法 Compositional

UICollectionView在iOS中是构建复杂布局的强大工具。iOS13中引入的UICollectionViewCompositionalLayout为创建自定义布局提供了全新的可能性。本文将深入探讨CompositionalLayout的工作原理,以及如何利用它创建复杂的分组、嵌套布局和增强视图。无论您是刚开始学习CompositionalLayout,还是想掌握它的高级用法,本文都将是您的完美指南。让我们开始这个令人兴奋的布局之旅吧!

本文所有代码示例见:https://github.com/kingnight/UICollectionCompositionalLayout

CollectionViewLayout由三个布局部分组成:

在iOS6中,包含UICollectionView的API可以被划分为三个不同的类别——Data、Layout和Presentation。这种区别是UICollectionView如此灵活的核心。当UICollectionView在iOS6中首次发布时,数据是通过基于索引路径的协议UICollectionViewDataSource来管理的。对于布局,有一个抽象类UICollectionViewLayout,一个具体的子类UICollectionViewFlowLayout。在展示方面,我们发布了两种视图类型UICollectionViewCell和UICollectionReusableView。

在iOS13中,我们分别为数据Data和布局Layout引入了两个新的组件,分别是DiffableDataSource和CompositionalLayout。这些API现在用于使用UICollectionViews构建应用程序。

创建UICollectionViewLayout

funcconfigLayout()->UICollectionViewLayout{\n//Groupwidth=1.0,superview是section,sectionparent是collectionviewlayout所以它会占据整个屏幕的宽度,height=0.2*它的superview的宽度也是section\nletitemSize=NSCollectionLayoutSize(widthDimension:.fractionalWidth(0.2),heightDimension:.fractionalHeight(1.0))\nletitem=NSCollectionLayoutItem(layoutSize:itemSize)\n\nletgroupSize=NSCollectionLayoutSize(widthDimension:.fractionalWidth(1.0),heightDimension:.fractionalWidth(0.2))\nletgroup=NSCollectionLayoutGroup.horizontal(layoutSize:groupSize,subitems:[item])\n\nletsection=NSCollectionLayoutSection(group:group)\nletlayout=UICollectionViewCompositionalLayout(section:section)\nreturnlayout\n

2、Item

(1)NSCollectionLayoutDimension

letabsoluteSize=NSCollectionLayoutSize(widthDimension:.absolute(44),\nheightDimension:.absolute(44))\n

如果内容的大小可能在运行时发生变化,例如在加载数据或响应系统字体大小的变化时,请使用估定值。您提供一个初始估计大小,系统稍后计算实际值。

letestimatedSize=NSCollectionLayoutSize(widthDimension:.estimated(200),\nheightDimension:.estimated(100))

使用一个小数来定义一个相对于Item容器尺寸的值。此选项简化了指定长宽比。例如,下面的元素的宽度和高度都等于其容器宽度的20%,从而创建了一个随容器大小变化而变大或缩小的正方形。

letfractionalSize=NSCollectionLayoutSize(widthDimension:.fractionalWidth(0.2),\nheightDimension:.fractionalWidth(0.2))

3、Groups

5、ItemSize计算

假设集合视图,宽度=428,屏幕宽度=428,计算itemsize:

6、配置DataSource

(1)snapshot

(2)ApplySnapShottoDataSource(TheTruth)

调整item的宽度占满整个屏幕,类似UITableViewCell布局:

interGroupSpacing→图9所示部分中组之间的空间大小。由于目前每一行是一个Group,每个Group里有一个Item。

sectioncontentInsets→section内容与其边界之间的空间大小。

NSDirectionalEdgeInsets→考虑了语言方向的边嵌入集。

group.contentInsets→计算出元素的位置后,元素内容周围用于调整最终大小的空间大小。内容嵌入到组中每个项目的每个边缘。所以你现在可以想我们可以有很多变化来添加边内嵌。

我们也可以在Item级别上指定,注意顺序很重要,如图13所示,我们在创建group后指定项目内容内嵌,在这种情况下,它将不起作用(对比图13vs14):

在图13中可以看到,我们创建了基于两列的布局。你应该看到的新东西是我们正在构建组,它以稍微不同的方式表示每一行。我们使用了另一种形式的初始化器,它接受显式的count参数,这里我们显式地指定了每组或每行只有两个元素。现在,这导致组合布局自动计算出元素的宽度必须是多少。我们在这里指定了元素的宽度,因为我们总是必须。我们说的是容器的100%但是顶部的宽度值会被覆盖。当你要求每组元素的数量时,组合布局将覆盖并计算满足我们请求实际需要的任何宽度。

funcconfigLayout()->UICollectionViewLayout{\nletitemSize=NSCollectionLayoutSize(widthDimension:.fractionalWidth(1.0),heightDimension:.fractionalHeight(1.0))\nletitem=NSCollectionLayoutItem(layoutSize:itemSize)\n\nletgroupSize=NSCollectionLayoutSize(widthDimension:.fractionalWidth(1.0),heightDimension:.absolute(44))\nletgroup=NSCollectionLayoutGroup.horizontal(layoutSize:groupSize,subitem:item,count:2)\nletspacing=CGFloat(10)\ngroup.interItemSpacing=.fixed(spacing)\ngroup.contentInsets=NSDirectionalEdgeInsets(top:0,leading:10,bottom:0,trailing:10)\n\nletsection=NSCollectionLayoutSection(group:group)\nsection.interGroupSpacing=spacing\nsection.contentInsets=NSDirectionalEdgeInsets(top:0,leading:10,bottom:20,trailing:10)\n\nletlayout=UICollectionViewCompositionalLayout(section:section)\nreturnlayout\n}

图16

定制CompositionalLayout

1、定制Model与Cell

classTopApp:UICollectionViewCell{\n@IBOutletweakvartitle:UILabel!\n@IBOutletweakvarsubTitle:UILabel!\n@IBOutletweakvarappImageView:UIImageView!\nstaticletreuseIdentifier="TopApp"\noverrideclassfuncawakeFromNib(){\nsuper.awakeFromNib()\n}\n}\n\nstructTopAppModel:Hashable{\nletimageNamed:String\nlettitle:String\nletsubTitle:String\nletidentifier=UUID().uuidString\n\nstaticvarmock:[TopAppModel]{\nreturn[\nTopAppModel(imageNamed:"externaldrive.connected.to.line.below",title:"facebooktitle",subTitle:"facebooksubtitle"),\nTopAppModel(imageNamed:"personalhotspot.circle.fill",title:"instagramtitle",subTitle:"instagramsubtitle"),\nTopAppModel(imageNamed:"bolt.horizontal.fill",title:"linkedintitle",subTitle:"linkedinsubtitle")\n\n]\n}\n}

2、每个Section不同分布

funccreateTopAppLayout()->NSCollectionLayoutSection{\nletitemSize=NSCollectionLayoutSize(widthDimension:.fractionalWidth(1.0),heightDimension:.fractionalHeight(1.0))\nletitem=NSCollectionLayoutItem(layoutSize:itemSize)\n\nletgroupSize=NSCollectionLayoutSize(widthDimension:.fractionalWidth(1.0),heightDimension:.absolute(74))\nletgroup=NSCollectionLayoutGroup.horizontal(layoutSize:groupSize,subitems:[item])\n\nletsection=NSCollectionLayoutSection(group:group)\nsection.interGroupSpacing=10\nsection.contentInsets=NSDirectionalEdgeInsets(top:10,leading:0,bottom:0,trailing:0)\nreturnsection\n}\n\nfunccreateFeatureCellLayout()->NSCollectionLayoutSection{\nletitemSize=NSCollectionLayoutSize(widthDimension:.fractionalWidth(0.48),heightDimension:.fractionalHeight(1.0))\nletitem=NSCollectionLayoutItem(layoutSize:itemSize)\n\nletgroupSize=NSCollectionLayoutSize(widthDimension:.fractionalWidth(1.0),heightDimension:.absolute(300))\nletgroup=NSCollectionLayoutGroup.horizontal(layoutSize:groupSize,subitems:[item])\ngroup.interItemSpacing=.flexible(10)\n\nletsection=NSCollectionLayoutSection(group:group)\nsection.interGroupSpacing=10\nsection.contentInsets=NSDirectionalEdgeInsets(top:10,leading:10,bottom:10,trailing:10)\nreturnsection\n}\n\nfuncconfigLayout2()->UICollectionViewLayout{\nletlayout=UICollectionViewCompositionalLayout{[weakself]sectionIndex,layoutEnvironmentin\nifsectionIndex==0{\nreturnself?.createTopAppLayout()\n}\nelseifsectionIndex==1{\nreturnself?.createFeatureCellLayout()\n}\nelse{\nreturnself?.createNestedGroupLayout()\n}\n}\nreturnlayout\n}

section不同布局:

@available(iOS13.0,*)\n@MainActoropenclassUICollectionViewCompositionalLayout:UICollectionViewLayout{\n\npublicinit(section:NSCollectionLayoutSection)\n\npublicinit(section:NSCollectionLayoutSection,configuration:UICollectionViewCompositionalLayoutConfiguration)\n\n\npublicinit(sectionProvider:@escapingUICollectionViewCompositionalLayoutSectionProvider)\n\npublicinit(sectionProvider:@escapingUICollectionViewCompositionalLayoutSectionProvider,configuration:UICollectionViewCompositionalLayoutConfiguration)\n\n\n//Settingthispropertywillinvalidatethelayoutimmediatelytoaffectanychanges\n//Note:anychangesmadetopropertiesdirectlywillhavenoeffect.\n@NSCopyingopenvarconfiguration:UICollectionViewCompositionalLayoutConfiguration\n}\n\n\npublictypealiasUICollectionViewCompositionalLayoutSectionProvider=(Int,NSCollectionLayoutEnvironment)->NSCollectionLayoutSection?\n\n\nNSCollectionLayoutSpacing→一个定义集合视图中元素之间或元素周围空间的对象。在集合视图布局中,你可以使用spacing对象来指定空间大小和计算空间大小的方式。可以使用fixed或flexible的间距来表示间距:使用fixed间距来提供精确数量的空间。例如,下面的代码在组中的项之间创建10个点的间距;使用flexible间距来提供最小的间距,可以随着更多空间的可用性而增长。例如,下面的代码在组中的项之间创建至少10个点的空间。当有更多可用空间时,Item会在额外空间中均匀分布。

3、嵌套布局组NestedLayoutGroup

compositionallayout的核心就是布局,layoutgroup实际上是NSCollectionLayoutItem的一个子类型classNSCollectionLayoutGroup:NSCollectionLayoutItem,因为这个关系,当你指定布局组中的Item时,你可以嵌套Group。这种特殊的嵌套没有限制,是任意的。因为我们有了这个,它开启了许多有趣的新设计。

在下面这个例子中,group由三个item组成,在左侧有一个大Item,右侧有一个垂直Group,包含两个子Item

4、嵌套CollectionView

如下图所示,我们创建的布局中item将占据整个屏幕,宽度和高度是恒定的或绝对的,其中重要的一点是orthogonalScrollingBehavior=.continuous。

orthogonalScrollingBehavior:相对于主布局轴的部分滚动行为。

在下图中可以看到,我们注释掉了orthogonalScrollingBehavior,因此它使用默认值none→该部分不允许用户正交滚动其内容。所以它垂直地添加item:

图19-注释掉了orthogonalScrollingBehavior垂直地添加item

如下面动图所示,section.orthogonalScrollingBehavior=.paging我们使用分页作为orthogonalScrollingBehavior的值,它会进行一项一项的滚动。

如下图所示,我们创建了三个Item的嵌套组,并创建了白色矩形来指定每个组,因此通过使用。grouppaging,当您滚动时,您将看到另一个组,简而言之,总是滚动停止时,组开始:

通过使用.grouppagingcentered,当你滚动时,它将进行组分页,并将组放在屏幕的中心:

测试1-类似AppStore的UI,但是每一個高度都稍微不太一樣:

//提供三種不同形狀的item\nletlayoutSize=NSCollectionLayoutSize(widthDimension:.absolute(110),heightDimension:.absolute(45))\nletitem=NSCollectionLayoutItem(layoutSize:layoutSize)\nletlayoutSize2=NSCollectionLayoutSize(widthDimension:.absolute(110),heightDimension:.absolute(65))\nletitem2=NSCollectionLayoutItem(layoutSize:layoutSize2)\nletlayoutSize3=NSCollectionLayoutSize(widthDimension:.absolute(110),heightDimension:.absolute(85))\nletitem3=NSCollectionLayoutItem(layoutSize:layoutSize3)\n\n//給剛好大小的group\nletgroupLayoutSize=NSCollectionLayoutSize(widthDimension:.absolute(110),heightDimension:.absolute(205))//45+65+85=195\n\n//用.vertical指明我們的group是垂直排列的\nletgroup=NSCollectionLayoutGroup.vertical(layoutSize:groupLayoutSize,subitems:[item,item2,item3])\n\n//這裡指的是垂直的間距了\ngroup.interItemSpacing=.fixed(5)//2*5=10\n\ngroup.edgeSpacing=NSCollectionLayoutEdgeSpacing(leading:nil,top:nil,trailing:.fixed(10),bottom:nil)\n\nletsection=NSCollectionLayoutSection(group:group)\nsection.orthogonalScrollingBehavior=.continuousGroupLeadingBoundary\nletlayout=UICollectionViewCompositionalLayout(section:section)\nreturnlayout

我们使用group.edgeSpacing来设定group的边界距离。这个edgeSpacing是一个类型为NSCollectionLayoutEdgeSpacing的属性,它的初始化方法长这样:init(leading:NSCollectionLayoutSpacing?,top:NSCollectionLayoutSpacing?,trailing:NSCollectionLayoutSpacing?,bottom:NSCollectionLayoutSpacing?),利用这个对象,我们可以描述一个方型的上下左右的边界距离。

6、自定义布局CustomLayout

从这个看起来像小朋友下楼梯的layout开始,我们可以看看如何做出完全定制的grouplayout,也就是如何利用NSCollectionLayoutGroup的.custom这个buildermethod。

letheight:CGFloat=120.0\nletgroupLayoutSize=NSCollectionLayoutSize(widthDimension:.fractionalWidth(1),heightDimension:.absolute(height))\nletgroup=NSCollectionLayoutGroup.custom(layoutSize:groupLayoutSize){(env)->[NSCollectionLayoutGroupCustomItem]in\nletsize=env.container.contentSize\nletspacing:CGFloat=8.0\nletitemWidth=(size.width-spacing*4)/3.0\nreturn[\nNSCollectionLayoutGroupCustomItem(frame:CGRect(x:0,y:0,width:itemWidth,height:height/3.0)),\nNSCollectionLayoutGroupCustomItem(frame:CGRect(x:(itemWidth+spacing),y:height/3.0,width:itemWidth,height:height/3.0)),\nNSCollectionLayoutGroupCustomItem(frame:CGRect(x:((itemWidth+spacing)*2),y:height*2/3.0,width:itemWidth,height:height/3.0))\n]\n}

这个地方看起来有点复杂,让我们先从.custom的定义开始看起:

openclassfunccustom(layoutSize:NSCollectionLayoutSize,itemProvider:@escapingNSCollectionLayoutGroupCustomItemProvider)

这里的.custom是指明我们这个group里面的layout要我们自己来决定,它的第一个参数layoutSize大家都应该非常熟悉了,就是指定这个group的大小。

那么什么是itemProvider呢?它实际上是一个(NSCollectionLayoutEnvironment)->[NSCollectionLayoutGroupCustomItem]的闭包,在系统准备呈现item之前,会调用这个闭包,请求闭包提供每一个item的位置信息。这个闭包会传入一个代表容器的NSCollectionLayoutEnvironment对象进来,然后我们就可以利用这个environment提供的信息,来计算item的大小和位置,并且在闭包把算好的item大小和位置,通过类型是NSCollectionLayoutGroupCustomItem的对象传出来,返回值是一个array,代表的是你需要指明这个group总共会有几个item。

所以你会看到上面我们通过env.container.contentSize获取容器的大小,也就是group的大小。利用这个信息,算出这个group里面的三个对象的绝对位置,再用NSCollectionLayoutGroupCustomItem打包位置信息传回去;而拿到这些信息的NSCollectionLayoutGroup,就可以知道在这个group里面如何呈现这些item了。

辅助视图Supplementaryview

CollectionView管理着三个基本的视图类:cell,supplementaryitems,decorationitems。

Supplementaryview的常见用途,三个方面:Badge,页眉和页脚。页眉和页脚支持固定或随内容滚动。

新类型,NSCollectionLayoutAnchor。

(1)右上角外移

这里我们看到我们马上创建了NSCollectionLayoutAnchor。我们指定edge。我们希望这个badge被固定在该特定单元格的顶部尾部。我们想让它跳出几何图形,向外突出极小的高度,它们并不在Cell本身的几何结构中。这个fractionalOffset偏移让我们有能力往外移。

在X轴正方向处移动30%在负Y处也移动30%,然后我们用badgeSize和elementKind定义了CollectionLayout的SupplementaryItem。引用CollectionView的视图类用那个注册的Supplementaryview类型。然后指定容器的锚点,指定它将如何关联。现在我们有了supplementary的定义,我们需要把它和某个东西联系起来。它需要与一个元素,一个单元格相关联。在这个例子中我们会用一个扩展的初始化方法来初始化它,它接受一个supplementary的数组。

(2)左上角内顶点

如下图所示,我们将badge移动到topleading位置,并且fractionalOffset是item的偏移量,指定0,它将badge锚定在item内。

如果我们想告诉CompositionalLayout我们想要supplementaryviews,我们需要将它们关联到NSCollectionLayoutItem或NSCollectionLayoutGroup。这可以通过init或稍后的supplementaryItems属性来实现。这两种情况都需要一个NSCollectionLayoutSupplementaryItem类型的数组。这个类允许我们定义supplementaryitems。你不能在section上添加NSCollectionLayoutSupplementaryItemItem。对于section,NSCollectionLayoutBoundarySupplementaryItem,我们将在下一节中看到。

(3)NSCollectionLayoutAnchor

NSCollectionLayoutAnchor→定义如何将supplementaryitem附加到集合视图中的Item上的对象。可以使用锚点将supplementaryitem附加到特定Item。锚点包含有关supplementaryitem在item上的位置的信息,包括:

classBadgeSupplementaryView:UICollectionReusableView{\nstaticletreuseIdentifer="BadgeSupplementaryView"\n\noverrideinit(frame:CGRect){\nsuper.init(frame:frame)\nself.backgroundColor=.green\nself.clipsToBounds=true\nself.layer.cornerRadius=10\n}\n\nrequiredinit?(coder:NSCoder){\nfatalError("init(coder:)hasnotbeenimplemented")\n}\n}

(4)页眉&页脚

structElementKind{\nstaticletbadge="badge-element-kind"\nstaticletbackground="background-element-kind"\nstaticletsectionHeader="section-header-element-kind"\nstaticletsectionFooter="section-footer-element-kind"\nstaticletlayoutHeader="layout-header-element-kind"\nstaticletlayoutFooter="layout-footer-element-kind"\n}

如下图所示,我们做了一些事情:

NSCollectionLayoutBoundarySupplementaryItem→与部分边界边相关的supplementaryitems的数组,例如页眉和页脚。

NSCollectionLayoutSupplementaryItem→一个对象,用于添加页眉或页脚的集合视图。边界supplementaryitem是supplementaryitem的特殊类型(NSCollectionLayoutSupplementaryItem)。可以使用边界supplementaryitem向集合视图的某个部分或整个集合视图添加页眉或页脚。每种类型的supplementaryitem项必须具有唯一的元素类型。考虑以一种可以直接识别每个元素的方式一起跟踪这些字符串。

Diffable数据源有一个supplementaryViewProvider属性,我们可以用它来提供supplementaryviews。这可以是一个闭包,也可以定义一个方法,该方法接受collectionview、kind和indexPath,并分配这个方法。

注册supplementaryview非常重要,否则应用程序会崩溃:

(5)固定header和footer

如图33所示,我们固定了header和footer:

pinToVisibleBounds→布尔值,表示页眉或页脚是固定在它所附加的部分或布局的顶部或底部可见边界上。这个属性的默认值为false,表示边界补充项(页眉或页脚)在滚动期间保持在原来的位置,并在其部分或布局滚动时移动到屏幕外。将该属性的值设置为true,以将边界补充项固定在它所附加的部分或布局的可见边界上。这样,在显示边界补充项时,它所附加的部分或布局的任何部分都是可见的。

zindex→补充项相对于该段内其他项的垂直堆叠顺序。这个属性用于在布局过程中确定元素从前到后的顺序。具有较高索引值的项目出现在具有较低索引值的项目的顶部。具有相同值的元素具有不确定的顺序。

(7)多个Badge同时展示

现在我们在每个项目中添加了两个badge,注意每个supplementaryitem都应该有唯一的elementKind,还有一件事elementKind可以是任何字符串。

2、DecorationItems

除了supplementaryitems之外,我们还可以使用装饰项DecorationItems自定义section布局。这将允许我们轻松地为section添加背景。我们要创建的背景视图非常简单(一个带圆角半径的灰色矩形),所以用代码来完成。

好吧。到目前为止,你已经使用了全新的iOS13card演示,整个card设计语言贯穿整个系统。我们在滚动UI中也看到了这一点所有内容都与卡片逻辑地组合在一起。这很适合CollectionView因为我们一直支持装饰视图的概念。在过去,你必须自己计算。好吧,现在我们使用组合布局让它简单了很多。我们用CollectionLayoutDecorationItem来支持它。你只需要用elementkind创建它,就可以了。这是用来在section内容背后建立一个视图给你漂亮的视觉分组。要构建它,只需要一行代码。然后将它添加到section中,你只需要指定Item就可以了。

如下图所示,我们为背景视图创建了布局,它将为每个部分显示,我们使用布局进行注册。

layout.register(BackgroundSupplementaryView.self,forDecorationViewOfKind:“background”)→注册一个类,用于为集合视图创建装饰视图。这个方法让布局对象有机会注册一个装饰视图,在集合视图中使用。装饰视图为部分或整个集合视图提供可视化的装饰,但不与集合视图的数据源提供的数据绑定。你不需要显式地创建装饰视图。注册一个后,由layout对象决定何时需要一个装饰视图,并从它的layoutAttributesForElements(in:)方法返回相应的布局属性。对于指定装饰视图的布局属性,集合视图创建(或重用)一个视图,并根据注册的信息自动显示它。如果您以前使用相同的类型字符串注册了类或nib文件,则您在viewClass参数中指定的类将替换旧条目。如果你想注销装饰视图,可以为viewClass指定nil。

背景卡视图,将每个部分背景视图显示为卡片:

3、全局Header,Footer和DecorativeView

如下图所示,我们在布局中全局添加了header和footer,而不是section,因为section和footer的pinToVisibleBounds是true,所以它将在屏幕上可见。

UICollectionViewCompositionalLayoutConfiguration→定义滚动方向、区域间距和布局的页眉或页脚的对象。你可以使用布局配置来修改集合视图布局的默认滚动方向,在布局的每个部分之间添加额外的间距,并为整个布局添加页眉或页脚。你可以在创建UICollectionViewCompositionalLayout时传入这个配置,或者你可以在现有的布局上设置configuration属性。如果在现有布局上修改配置,系统会使布局失效,以便用新的配置更新它。

如下图所示,现在注释pinToVisibleBounds,当滚动全局header和footer时,也会滚动:

通过学习本文,我们全面了解了UICollectionViewCompositionalLayout的强大功能。它通过Item、Group和Section的分层结构,为构建复杂的自定义布局提供了巨大的灵活性。我们还学习了各种高级布局技巧,如嵌套布局组、装饰视图、全局头尾等。CompositionalLayout使我们可以用声明式代码优雅地表达布局意图。它是在iOS上构建复杂滚动UI的未来方向。希望本文能让您对CompositionalLayout有更深的理解,并在项目中大胆运用它。掌握它,我们就能创造出更加惊人的用户体验!

出处:https://mp.weixin.qq.com/s/VnYLUV-8ft_qiRe-0b-Nhg

好了,文章到这里就结束啦,如果本次分享的compositional是什么意思,compositional的意思翻译、用法和Compositional问题对您有所帮助,还望关注下本站哦!

本站涵盖的内容、图片、视频等数据,部分未能与原作者取得联系。若涉及版权问题,请及时通知我们并提供相关证明材料,我们将及时予以删除!谢谢大家的理解与支持!

Copyright © 2023