使用UITableViewAutomaticDimension使用嵌入式UICollectionView创建UITableView [英] Making UITableView with embedded UICollectionView using UITableViewAutomaticDimension
问题描述
我想创建一个 UITableView
,带有标题标签和嵌入式 UICollectionView
(它知道它的大小)带有一些图标使用 UITableViewAutomaticDimension
。问题是 UITableView
当我在里面有 UICollectionView
时,弄清楚单元格高度有问题。我必须滚动 UITableView
才能重新计算大小。但即便如此,它也存在高度问题(如果从较大的高度重复使用它会太大)。除了 UICollectionView
中的图标之外,从请求中不知道,但它们是从服务器加载的。
我还尝试为 UICollectionView
创建一个高度约束,但这样我就得到了无法同时满足与 UIView-Encapsulated-Layout-Height
冲突导致的约束,无论如何我的约束都被删除了。
我创建了一个带有示例项目的GitHub存储库(尽可能简单):
这是输出
希望它对您有所帮助
编辑/更新
你有很多您的演示项目中的问题。
我在您的演示项目中做了很多更改。
在故事板中复制并粘贴 XML
。
不要忘记连接高度限制
这是完整的故事板 XML
<?xml version =1.0encoding =UTF- 8\" >?;
< document type =com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIBversion =3.0toolsVersion =13771targetRuntime =iOS.CocoaTouchpropertyAccessControl =noneuseAutolayout =YESuseTraitCollections =是useSafeAreas =YEScolorMatched =YESinitialViewController =BYZ-38-t0r>
< device id =retina4_7orientation =portrait>
< adaptation id =fullscreen/>
< / device>
< dependencies>
< deployment identifier =iOS/>
< plugIn identifier =com.apple.InterfaceBuilder.IBCocoaTouchPluginversion =13772/>
< capability name =安全区域布局指南minToolsVersion =9.0/>
< capability name =以Xcode 8格式保存的文档minToolsVersion =8.0/>
< / dependencies>
< scenes>
<! - View Controller - >
< scene sceneID =tne-QT-ifu>
< objects>
< viewController id =BYZ-38-t0rcustomClass =ViewControllercustomModule =CollectionViewInTableViewcustomModuleProvider =targetsceneMemberID =viewController>
< view key =viewcontentMode =scaleToFillid =8bC-Xf-vdC>
< rect key =framex =0.0y =0.0width =375height =667/>
< autoresizingMask key =autoresizingMaskwidthSizable =YESheightSizable =YES/>
< subviews>
< tableView clipsSubviews =YEScontentMode =scaleToFillalwaysBounceVertical =YESdataMode =prototypesstyle =plainseparatorStyle =defaultrowHeight =196estimatedRowHeight = - 1sectionHeaderHeight = 28sectionFooterHeight =28translatesAutoresizingMaskIntoConstraints =NOid =ZhZ-if-Yia>
< rect key =framex =0.0y =0.0width =375height =667/>
< color key =backgroundColorwhite =1alpha =1colorSpace =customcustomColorSpace =genericGamma22GrayColorSpace/>
< prototypes>
< tableViewCell clipsSubviews =YEScontentMode =scaleToFillpreservesSuperviewLayoutMargins =YESselectionStyle =defaultindentationWidth =10reuseIdentifier =cellrowHeight =196id =1WO-2S-MI9 customClass =FooTableViewCellcustomModule =CollectionViewInTableViewcustomModuleProvider =target>
< rect key =framex =0.0y =28width =375height =196/>
< autoresizingMask key =autoresizingMask/>
将tableViewCellContentView键= 内容查看 不透明= NO clipsSubviews = YES multipleTouchEnabled = YES contentMode = 中心 preservesSuperviewLayoutMargins = YES insetsLayoutMarginsFromSafeArea = NO tableViewCell =1WO-2S-MI9 id =2lF-aM-Z2U>
< rect key =framex =0.0y =0.0width =375height =195.5/>
< autoresizingMask key =autoresizingMask/>
< subviews>
< label opaque =NOuserInteractionEnabled =NOcontentMode =lefthorizontalHuggingPriority =251verticalHuggingPriority =251text =TitletextAlignment =naturallineBreakMode =tailTruncationbaselineAdjustment = alignBaselinesadjustsFontSizeToFit =NOtranslatesAutoresizingMaskIntoConstraints =NOid =vs4-91-woo>
< rect key =framex =8y =8width =359height =20.5/>
< fontDescription key =fontDescriptiontype =systempointSize =17/>
< nil key =textColor/>
< nil key =highlightedColor/>
< / label>
< label opaque =NOuserInteractionEnabled =NOcontentMode =lefthorizontalHuggingPriority =251verticalHuggingPriority =251text =DescriptiontextAlignment =naturallineBreakMode =tailTruncationbaselineAdjustment = alignBaselinesadjustsFontSizeToFit =NOtranslatesAutoresizingMaskIntoConstraints =NOid =lD2-bR-lnm>
< rect key =framex =8y =36.5width =359height =20.5/>
< fontDescription key =fontDescriptiontype =systempointSize =17/>
< nil key =textColor/>
< nil key =highlightedColor/>
< / label>
< collectionView clipsSubviews =YESmultipleTouchEnabled =YEScontentMode =scaleToFilldataMode =prototypestranslatesAutoresizingMaskIntoConstraints =NOid =6sQ-gf-Y6xcustomClass =IconsCollectionViewcustomModule =CollectionViewInTableView customModuleProvider =target>
< rect key =framex =8y =65width =359height =92.5/>
< color key =backgroundColorwhite =1alpha =1colorSpace =customcustomColorSpace =genericGamma22GrayColorSpace/>
< constraints>
< constraint firstAttribute =heightation =greaterThanOrEqualpriority =750constant =88id =f9g-Du-pYg/>
< / constraints>
< collectionViewFlowLayout key =collectionViewLayoutminimumLineSpacing =10minimumInteritemSpacing =10id =Nts-Lf-FPD>
< size key =itemSizewidth =50height =50/>
< size key =headerReferenceSizewidth =0.0height =0.0/>
< size key =footerReferenceSizewidth =0.0height =0.0/>
< inset key =sectionInsetminX =0.0minY =0.0maxX =0.0maxY =0.0/>
< / collectionViewFlowLayout>
< cells>
< collectionViewCell opaque =NOclipsSubviews =YESmultipleTouchEnabled =YEScontentMode =centerreuseIdentifier =itemid =8gX-Q1-0jGcustomClass =BarCollectionViewCellcustomModule =CollectionViewInTableView customModuleProvider =target>
< rect key =framex =0.0y =0.0width =50height =50/>
< autoresizingMask key =autoresizingMaskflexibleMaxX =YESflexibleMaxY =YES/>
< view key =contentViewopaque =NOclipsSubviews =YESmultipleTouchEnabled =YEScontentMode =centerinsetsLayoutMarginsFromSafeArea =NO>
< rect key =framex =0.0y =0.0width =50height =50/>
< autoresizingMask key =autoresizingMask/>
< subviews>
将ImageView的clipsSubviews = YES userInteractionEnabled = NO contentMode = scaleAspectFill horizontalHuggingPriority = 251 verticalHuggingPriority = 251 translatesAutoresizingMaskIntoConstraints = NO ID = 6cf-UD-BQL >
< rect key =framex =0.0y =0.0width =50height =50/>
< / imageView>
< / subviews>
< / view>
< constraints>
< constraint firstAttribute =bottomsecondItem =6cf-uD-BQlsecondAttribute =bottomid =0c3-ug-8tN/>
< constraint firstItem =6cf-uD-BQlfirstAttribute =topsecondItem =8gX-Q1-0jGsecondAttribute =topid =9xW-dN-c0m/>
< constraint firstItem =6cf-uD-BQ1firstAttribute =leadingsecondItem =8gX-Q1-0jGsecondAttribute =leadingid =dT6-RU-eE4/>
< constraint firstAttribute =trailingsecondItem =6cf-uD-BQ1secondAttribute =trailingid =nnz-oA-GgP/>
< / constraints>
< connections>
< outlet property =iconImageViewdestination =6cf-uD-BQlid =lFo-SS-Ego/>
< / connections>
< / collectionViewCell>
< / cells>
< / collectionView>
将按钮不透明= NO contentMode = scaleToFill contentHorizontalAlignment = 右 contentVerticalAlignment = 中心 按钮类型= 圆角矩形 lineBreakMode = middleTruncation translatesAutoresizingMaskIntoConstraints = NO ID =SXA锰XXW >
< rect key =framex =8y =165.5width =359height =30/>
< state key =normaltitle =Button/>
< / button>
< / subviews>
< constraints>
< constraint firstItem =sXa-Mn-xxWfirstAttribute =leadingsecondItem =2lF-aM-Z2UsecondAttribute =leadingconstant =8id =4ix-8u-010/ >
< constraint firstAttribute =bottomsecondItem =sXa-Mn-xxWsecondAttribute =bottomid =50m-Bv-FF8/>
< constraint firstAttribute =trailingsecondItem =sXa-Mn-xxWsecondAttribute =trailingconstant =8id =8UW-vI-hge/>
< constraint firstItem =6sQ-gf-Y6xfirstAttribute =leadingsecondItem =2lF-aM-Z2UsecondAttribute =leadingconstant =8id =9ht-Ez-lJX/ >
< constraint firstAttribute =trailingsecondItem =vs4-91-woosecondAttribute =trailingconstant =8id =NOH-if-o7C/>
< constraint firstItem =lD2-bR-lnmfirstAttribute =leadingsecondItem =2lF-aM-Z2UsecondAttribute =leadingconstant =8id =S2D-Kj-50g/ >
< constraint firstItem =vs4-91-woofirstAttribute =leadingsecondItem =2lF-aM-Z2UsecondAttribute =leadingconstant =8id =atk-7U-Mrw/ >
< constraint firstAttribute =trailingsecondItem =6sQ-gf-Y6xsecondAttribute =trailingconstant =8id =bfY-uh-Su2/>
< constraint firstItem =vs4-91-woofirstAttribute =topsecondItem =2lF-aM-Z2UsecondAttribute =topconstant =8id =gYO-XW-lmk/ >
< constraint firstAttribute =trailingsecondItem =lD2-bR-lnmsecondAttribute =trailingconstant =8id =pkH-Pf-xE1/>
< constraint firstItem =sXa-Mn-xxWfirstAttribute =topsecondItem =6sQ-gf-Y6xsecondAttribute =bottomconstant =8id =w2O-4g-q6B/ >
< constraint firstItem =6sQ-gf-Y6xfirstAttribute =topsecondItem =lD2-bR-lnmsecondAttribute =bottomconstant =8id =xky-sw-IcM/ >
< constraint firstItem =lD2-bR-lnmfirstAttribute =topsecondItem =vs4-91-woosecondAttribute =bottomconstant =8id =yG3-dE-CjF/ >
< / constraints>
< / tableViewCellContentView>
< connections>
< outlet property =const_Height_CollectionViewdestination =f9g-Du-pYgid =gw7-9T-hiU/>
< outlet property =descriptionLabeldestination =lD2-bR-lnmid =M4K-k5-6LN/>
< outlet property =iconsCollectionViewdestination =6sQ-gf-Y6xid =FO2-dP-VNH/>
< outlet property =titleLabeldestination =vs4-91-wooid =HHy-1V-bTW/>
< / connections>
< / tableViewCell>
< / prototypes>
< / tableView>
< / subviews>
< color key =backgroundColorred =1green =1blue =1alpha =1colorSpace =customcustomColorSpace =sRGB/>
< constraints>
< constraint firstItem =ZhZ-if-YiafirstAttribute =topsecondItem =8bC-Xf-vdCsecondAttribute =topid =J8c-wQ-FxB/>
< constraint firstItem =ZhZ-if-YiafirstAttribute =bottomsecondItem =6Tk-OE-BBYsecondAttribute =bottomid =KCX-nj-zXy/>
< constraint firstItem =ZhZ-if-YiafirstAttribute =leadingsecondItem =6Tk-OE-BBYsecondAttribute =leadingid =QMU-w2-uUY/>
< constraint firstItem =ZhZ-if-YiafirstAttribute =trailingsecondItem =6Tk-OE-BBYsecondAttribute =trailingid =yx7-yg-aqC/>
< / constraints>
< viewLayoutGuide key =safeAreaid =6Tk-OE-BBY/>
< / view>
< connections>
< outlet property =tableViewdestination =ZhZ-if-Yiaid =WdR-nu-gjc/>
< / connections>
< / viewController>
<占位符占位符标识符=IBFirstResponderid =dkx-z0-nzrsceneMemberID =firstResponder/>
< / objects>
< point key =canvasLocationx =117.59999999999999y =118.29085457271366/>
< / scene>
< / scenes>
< / document>
FOOTableviewCell.swift
protocol TableViewDelegate {
func cellTapped(for:FooTableViewCell)
}
class FooTableViewCell:UITableViewCell {
static让singleCellHeight = 88;
@IBOutlet weak var titleLabel:UILabel!
@IBOutlet weak var descriptionLabel:UILabel!
@IBOutlet weak var iconsCollectionView:IconsCollectionView!
@IBOutlet weak var const_Height_CollectionView:NSLayoutConstraint!
var delegateCollection:TableViewDelegate?
var bars:[Bar] = [] {
didSet {
self.iconsCollectionView.reloadData()
iconsCollectionView.setNeedsLayout()
self.layoutIfNeeded()
const_Height_CollectionView.constant = iconsCollectionView.contentSize.height
self.layoutIfNeeded()
}
}
覆盖func awakeFromNib(){
iconsCollectionView .translatesAutoresizingMaskIntoConstraints = false
iconsCollectionView.initFlowLayout(superviewWidth:self.frame.width)
iconsCollectionView.setNeedsLayout()
iconsCollectionView.dataSource = self
iconsCollectionView.delegate = self
const_Height_CollectionView.constant = iconsCollectionView.contentSize.height
self.layoutIfNeeded()
self.setNeedsLayout()
}
func cellTapped(){
iconsCollectionView.setNeedsLayout()
self。 layoutIfNeeded()
self.setNeedsLayout()
const_Height_CollectionView.constant = iconsCollectionView.contentSize.height
self.delegateCollection?.cellTapped(for:self)
}
}
扩展名FooTableViewCell:UICollectionViewDataSource {
func collectionView(_ collectionView:UICollectionView,numberOfItemsInSection section:Int) - > Int {
return bars.count + 1
}
func collectionView(_ collectionView:UICollectionView,cellForItemAt indexPath:IndexPath) - > UICollectionViewCell {
让cell = collectionView.dequeueReusableCell(withReuseIdentifier:item,for:indexPath)为! BarCollectionViewCell
let row = indexPath.row
if(row> = bars.count){
cell.iconImageView.image = UIImage(named:add.png)
返回单元格
} else {
let bar = bars [row]
cell.iconImageView.image = UIImage(named:bar.imageName)
print(bar。 imageName)
返回单元格
}
}
}
扩展名FooTableViewCell:UICollectionViewDelegate {
func collectionView(_ collectionView:UICollectionView,didSelectItemAt indexPath:IndexPath){
// deselectItem(at:indexPath,animated:true)
if(indexPath.row> = bars。 count){//这是一个加号按钮
self.delegateCollection?.cellTapped(for:self)
}
}
}
IconCollectionView.swift
import UIKit
class IconsCollectionView:DynamicCollectionView {
var columnLayout:ColumnFlowLayout?
覆盖func awakeFromNib(){
}
func initFlowLayout(superviewWidth:CGFloat){
let layout = ColumnFlowLayout(
cellsPerRow:4,
superviewWidth:superviewWidth,
minimumInteritemSpacing:0,
minimumLineSpacing:0,
sectionInset:UIEdgeInsets(top:0,left:0,底部:0,右:0)
)
columnLayout =布局
collectionViewLayout =布局
}
}
ViewController.Swift
import UIKit
class ViewController:UIViewController {
@IBOutlet weak var tableView:UITableView!
var foos:[Foo] = []
var bars:[[Bar]] = [[]]
覆盖func viewDidLoad( ){
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
tableView.estimatedRowHeight = 188
tableView.rowHeight = UITableViewAutomaticDimension
for i in stride(from:1,to:10,by:1){
let foo = Foo()
foo.title =Item \( i)
foo.description =描述\(i)
foos.append(foo)
}
bars.removeAll()
for _ in 0 ..< foos.count {
bars.append(self.loadIconsSync())
}
}
func loadIconsSync() - > [Bar] {
var barObjects:[Bar] = []
let iconsCount = Utils.rnd(3,8)
for _ in stride(from :1,to:iconsCount,by:1){
barObjects.append(self.getRandomItem())
}
return barObjects
}
func getRandomItem() - > Bar {
let randomIndex = Utils.rnd(1,10)
let bar = Bar()
bar.imageName =icon_\(randomIndex).png
return bar
}
}
扩展名ViewController:UITableViewDataSource,UITableViewDelegate {
func tableView(_ tableView:UITableView,cellForRowAt indexPath:IndexPath ) - > UITableViewCell {
let foo = foos [indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier:cell,for:indexPath)as! FooTableViewCell
var bar = bars [indexPath.row]
cell.bars = bar
cell.titleLabel.text = foo.title
cell。 descriptionLabel.text = foo.description
cell.delegateCollection = self
self.view.layoutIfNeeded()
cell.const_Height_CollectionView.constant = cell.iconsCollectionView.contentSize.height
self。 view.layoutIfNeeded()
返回单元格
}
func tableView(_ tableView:UITableView,numberOfRowsInSection section:Int) - > Int {
return foos.count
}
}
扩展名ViewController:TableViewDelegate {
func cellTapped(对于obj:FooTableViewCell){
如果让indexPath = tableView.indexPath(for:obj){
bars [indexPath.row] .append(getRandomItem())
self.tableView.beginUpdates()
self .tableView.reloadRows(at:[indexPath],with:。auto]
self.tableView.endUpdates()
}
}
}
输出
编辑/更新2
我不知道方向支持和ipad支持。
现在当方向改变时我们必须重新布局集合视图。
所以逻辑是
总项目+ 1(+ 1因为加上图标)
项目大小*(总项目数/ 3) .rounded
假设您有7件商品
所以商品尺寸为93(每行)*(8 / 3).rounded = 279
因此,您需要根据iPad和横向模式的要求管理一些硬编码值。
现在我正在考虑每行3个对象与iPhone设计相同。
此处硬编码的单元格编号为3您可以管理自己的。
第1步:
在viewContorller.swift中添加以下方法
覆盖func viewWillTransition(大小:CGSize,带协调器:UIViewControllerTransitionCoordinator){
super.viewWillTransition(to:size,with:coordinator)
self.tableView.beginUpdates()
self.tableView.reloadData()
self.tableView.endUpdates()
}
替换cellForRowAtIndexPath
func tableView(_ tableView:UITableView ,cellForRowAt indexPath:IndexPath) - > UITableViewCell {
let foo = foos [indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier:cell,for:indexPath)as! FooTableViewCell
cell.iconsCollectionView.initFlowLayout(superviewWidth:self.tableView.frame.width)
let bar = bars [indexPath.row]
cell.bars = bar
cell.titleLabel.text = foo.title
cell.descriptionLabel.text = foo.description
cell.delegateCollection = self
self.view.layoutIfNeeded( )
let items:CGFloat = CGFloat(bar.count + 1)
let value =(items / 3.0).rounded(.awayFromZero)
cell.const_Height_CollectionView.constant = CGFloat的((cell.iconsCollectionView.collectionViewLayout作为!UICollectionViewFlowLayout).itemSize.height *值)
self.view.layoutIfNeeded()
cell.iconsCollectionView.setNeedsLayout()
返回cell
}
和
func tableView(_ tableView:UITableView,willDisplay cell:UITableViewCell,forRowAt indexPath:IndexPath){
如果让footCell = cell为? FooTableViewCell {
footCell.const_Height_CollectionView.constant = footCell.iconsCollectionView.contentSize.height
self.view.layoutIfNeeded()
}
}
在TableviewCell中
var bars:[Bar] = [] {
didSet {
self.iconsCollectionView.reloadData()
iconsCollectionView.setNeedsLayout()
self.layoutIfNeeded( )
let items:CGFloat = CGFloat(bars.count + 1)
let value =(items / 3.0).rounded(.awayFromZero)
const_Height_CollectionView。 constant = CGFloat((iconsCollectionView.collectionViewLayout as!UICollectionViewFlowLayout).itemSize.height * value)
self.layoutIfNeeded()
}
}
和
func cellTapped() {
iconsCollectionView.setNeedsLay out()
self.layoutIfNeeded()
self.setNeedsLayout()
let items:CGFloat = CGFloat(bars.count + 1)
let value = (items / 3.0).rounded(.awayFromZero)
const_Height_CollectionView.constant = CGFloat((iconsCollectionView.collectionViewLayout as! UICollectionViewFlowLayout).itemSize.height * value)
self.delegateCollection?.cellTapped(for: self)
}
I want to create an UITableView
with Title label and embedded UICollectionView
(which knows it's size) with some icons using UITableViewAutomaticDimension
. The problem is UITableView
has a problem with figuring out cell height when I have UICollectionView
inside. I have to scroll an UITableView
in order for it to recalculate sizes. But even then it has problems with height (it's too big if it was reused from bigger one). On top of that icons inside UICollectionView
aren't known from the begginging, but they are intended to be loaded from the server.
I've also tried to create a height constraint for an UICollectionView
, but this way I'm getting "Unable to simultaneously satisfy constraints" caused by conflict with UIView-Encapsulated-Layout-Height
and my own constraint is being removed anyway.
I've created a GitHub repository with a sample project (I did it as simple as possible):
https://github.com/piotrros/CollectionViewInTableView
As you are doing very much stuff in cellForRow
so it need time to ready and so when you scroll it is not showing properly
Check following things.
ViewController.swift
In View Did load
Add tableView.rowHeight = UITableViewAutomaticDimension
and replace this method
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let foo = foos[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! FooTableViewCell
cell.titleLabel.text = foo.title
cell.descriptionLabel.text = foo.description
self.view.layoutIfNeeded()
return cell
}
FooTableViewCell.swift
class FooTableViewCell: UITableViewCell {
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var stackView: UIStackView!
@IBOutlet weak var descriptionLabel: UILabel!
@IBOutlet weak var iconsCollectionView: IconsCollectionView!
@IBOutlet weak var const_Height_CollectionView: NSLayoutConstraint!
override func awakeFromNib() {
iconsCollectionView.translatesAutoresizingMaskIntoConstraints = false
iconsCollectionView.initFlowLayout(superviewWidth: self.frame.width)
iconsCollectionView.loadIconsSync()
iconsCollectionView.setNeedsLayout()
}
}
And I have removed StackView Form your storyboard and just give leading , trailing ,top and bottom constraints (Nothing complicated )
Here is output
Hope it is helpful to you
EDIT/UPDATE
YOu have many issues in your demo project. I have made many changes in your demo project.
Copy and paste XML
in storyboard.
DON'T FORGOT TO CONNECT HEIGHT CONSTRAINT
Here is complete storyboard XML
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13771" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="ViewController" customModule="CollectionViewInTableView" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="196" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="ZhZ-if-Yia">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="cell" rowHeight="196" id="1WO-2S-MI9" customClass="FooTableViewCell" customModule="CollectionViewInTableView" customModuleProvider="target">
<rect key="frame" x="0.0" y="28" width="375" height="196"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="1WO-2S-MI9" id="2lF-aM-Z2U">
<rect key="frame" x="0.0" y="0.0" width="375" height="195.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vs4-91-woo">
<rect key="frame" x="8" y="8" width="359" height="20.5"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Description" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="lD2-bR-lnm">
<rect key="frame" x="8" y="36.5" width="359" height="20.5"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="prototypes" translatesAutoresizingMaskIntoConstraints="NO" id="6sQ-gf-Y6x" customClass="IconsCollectionView" customModule="CollectionViewInTableView" customModuleProvider="target">
<rect key="frame" x="8" y="65" width="359" height="92.5"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" relation="greaterThanOrEqual" priority="750" constant="88" id="f9g-Du-pYg"/>
</constraints>
<collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="10" minimumInteritemSpacing="10" id="Nts-Lf-FPD">
<size key="itemSize" width="50" height="50"/>
<size key="headerReferenceSize" width="0.0" height="0.0"/>
<size key="footerReferenceSize" width="0.0" height="0.0"/>
<inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
</collectionViewFlowLayout>
<cells>
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="item" id="8gX-Q1-0jG" customClass="BarCollectionViewCell" customModule="CollectionViewInTableView" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="50" height="50"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO">
<rect key="frame" x="0.0" y="0.0" width="50" height="50"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="6cf-uD-BQl">
<rect key="frame" x="0.0" y="0.0" width="50" height="50"/>
</imageView>
</subviews>
</view>
<constraints>
<constraint firstAttribute="bottom" secondItem="6cf-uD-BQl" secondAttribute="bottom" id="0c3-ug-8tN"/>
<constraint firstItem="6cf-uD-BQl" firstAttribute="top" secondItem="8gX-Q1-0jG" secondAttribute="top" id="9xW-dN-c0m"/>
<constraint firstItem="6cf-uD-BQl" firstAttribute="leading" secondItem="8gX-Q1-0jG" secondAttribute="leading" id="dT6-RU-eE4"/>
<constraint firstAttribute="trailing" secondItem="6cf-uD-BQl" secondAttribute="trailing" id="nnz-oA-GgP"/>
</constraints>
<connections>
<outlet property="iconImageView" destination="6cf-uD-BQl" id="lFo-SS-Ego"/>
</connections>
</collectionViewCell>
</cells>
</collectionView>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="right" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="sXa-Mn-xxW">
<rect key="frame" x="8" y="165.5" width="359" height="30"/>
<state key="normal" title="Button"/>
</button>
</subviews>
<constraints>
<constraint firstItem="sXa-Mn-xxW" firstAttribute="leading" secondItem="2lF-aM-Z2U" secondAttribute="leading" constant="8" id="4ix-8u-0lO"/>
<constraint firstAttribute="bottom" secondItem="sXa-Mn-xxW" secondAttribute="bottom" id="50m-Bv-FF8"/>
<constraint firstAttribute="trailing" secondItem="sXa-Mn-xxW" secondAttribute="trailing" constant="8" id="8UW-vI-hge"/>
<constraint firstItem="6sQ-gf-Y6x" firstAttribute="leading" secondItem="2lF-aM-Z2U" secondAttribute="leading" constant="8" id="9ht-Ez-lJX"/>
<constraint firstAttribute="trailing" secondItem="vs4-91-woo" secondAttribute="trailing" constant="8" id="NOH-if-o7C"/>
<constraint firstItem="lD2-bR-lnm" firstAttribute="leading" secondItem="2lF-aM-Z2U" secondAttribute="leading" constant="8" id="S2D-Kj-5Og"/>
<constraint firstItem="vs4-91-woo" firstAttribute="leading" secondItem="2lF-aM-Z2U" secondAttribute="leading" constant="8" id="atk-7U-Mrw"/>
<constraint firstAttribute="trailing" secondItem="6sQ-gf-Y6x" secondAttribute="trailing" constant="8" id="bfY-uh-Su2"/>
<constraint firstItem="vs4-91-woo" firstAttribute="top" secondItem="2lF-aM-Z2U" secondAttribute="top" constant="8" id="gYO-XW-lmk"/>
<constraint firstAttribute="trailing" secondItem="lD2-bR-lnm" secondAttribute="trailing" constant="8" id="pkH-Pf-xE1"/>
<constraint firstItem="sXa-Mn-xxW" firstAttribute="top" secondItem="6sQ-gf-Y6x" secondAttribute="bottom" constant="8" id="w2O-4g-q6B"/>
<constraint firstItem="6sQ-gf-Y6x" firstAttribute="top" secondItem="lD2-bR-lnm" secondAttribute="bottom" constant="8" id="xky-sw-IcM"/>
<constraint firstItem="lD2-bR-lnm" firstAttribute="top" secondItem="vs4-91-woo" secondAttribute="bottom" constant="8" id="yG3-dE-CjF"/>
</constraints>
</tableViewCellContentView>
<connections>
<outlet property="const_Height_CollectionView" destination="f9g-Du-pYg" id="gw7-9T-hiU"/>
<outlet property="descriptionLabel" destination="lD2-bR-lnm" id="M4K-k5-6LN"/>
<outlet property="iconsCollectionView" destination="6sQ-gf-Y6x" id="FO2-dP-VNH"/>
<outlet property="titleLabel" destination="vs4-91-woo" id="HHy-1V-bTW"/>
</connections>
</tableViewCell>
</prototypes>
</tableView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="ZhZ-if-Yia" firstAttribute="top" secondItem="8bC-Xf-vdC" secondAttribute="top" id="J8c-wQ-FxB"/>
<constraint firstItem="ZhZ-if-Yia" firstAttribute="bottom" secondItem="6Tk-OE-BBY" secondAttribute="bottom" id="KCX-nj-zXy"/>
<constraint firstItem="ZhZ-if-Yia" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" id="QMU-w2-uUY"/>
<constraint firstItem="ZhZ-if-Yia" firstAttribute="trailing" secondItem="6Tk-OE-BBY" secondAttribute="trailing" id="yx7-yg-aqC"/>
</constraints>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
</view>
<connections>
<outlet property="tableView" destination="ZhZ-if-Yia" id="WdR-nu-gjc"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="117.59999999999999" y="118.29085457271366"/>
</scene>
</scenes>
</document>
FOOTableviewCell.swift
protocol TableViewDelegate {
func cellTapped (for:FooTableViewCell)
}
class FooTableViewCell: UITableViewCell {
static let singleCellHeight = 88;
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var descriptionLabel: UILabel!
@IBOutlet weak var iconsCollectionView: IconsCollectionView!
@IBOutlet weak var const_Height_CollectionView: NSLayoutConstraint!
var delegateCollection : TableViewDelegate?
var bars:[Bar] = [] {
didSet {
self.iconsCollectionView.reloadData()
iconsCollectionView.setNeedsLayout()
self.layoutIfNeeded()
const_Height_CollectionView.constant = iconsCollectionView.contentSize.height
self.layoutIfNeeded()
}
}
override func awakeFromNib() {
iconsCollectionView.translatesAutoresizingMaskIntoConstraints = false
iconsCollectionView.initFlowLayout(superviewWidth: self.frame.width)
iconsCollectionView.setNeedsLayout()
iconsCollectionView.dataSource = self
iconsCollectionView.delegate = self
const_Height_CollectionView.constant = iconsCollectionView.contentSize.height
self.layoutIfNeeded()
self.setNeedsLayout()
}
func cellTapped () {
iconsCollectionView.setNeedsLayout()
self.layoutIfNeeded()
self.setNeedsLayout()
const_Height_CollectionView.constant = iconsCollectionView.contentSize.height
self.delegateCollection?.cellTapped(for: self)
}
}
extension FooTableViewCell : UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return bars.count + 1
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "item", for: indexPath) as! BarCollectionViewCell
let row = indexPath.row
if(row >= bars.count) {
cell.iconImageView.image = UIImage(named: "add.png")
return cell
} else {
let bar = bars[row]
cell.iconImageView.image = UIImage(named: bar.imageName)
print(bar.imageName)
return cell
}
}
}
extension FooTableViewCell : UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
//deselectItem(at: indexPath, animated: true)
if(indexPath.row >= bars.count) { //it's a plus button
self.delegateCollection?.cellTapped(for: self)
}
}
}
IconCollectionView.swift
import UIKit
class IconsCollectionView: DynamicCollectionView {
var columnLayout:ColumnFlowLayout?
override func awakeFromNib() {
}
func initFlowLayout(superviewWidth:CGFloat) {
let layout = ColumnFlowLayout(
cellsPerRow: 4,
superviewWidth: superviewWidth,
minimumInteritemSpacing: 0,
minimumLineSpacing: 0,
sectionInset: UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
)
columnLayout = layout
collectionViewLayout = layout
}
}
ViewController.Swift
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var tableView: UITableView!
var foos:[Foo] = []
var bars:[[Bar]] = [[]]
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
tableView.estimatedRowHeight = 188
tableView.rowHeight = UITableViewAutomaticDimension
for i in stride(from: 1, to: 10, by: 1) {
let foo = Foo()
foo.title = "Item \(i)"
foo.description = "Description \(i)"
foos.append(foo)
}
bars.removeAll()
for _ in 0 ..< foos.count {
bars.append(self.loadIconsSync())
}
}
func loadIconsSync() -> [Bar] {
var barObjects :[Bar] = []
let iconsCount = Utils.rnd(3, 8)
for _ in stride(from: 1, to: iconsCount, by: 1) {
barObjects.append(self.getRandomItem())
}
return barObjects
}
func getRandomItem() -> Bar {
let randomIndex = Utils.rnd(1, 10)
let bar = Bar()
bar.imageName = "icon_\(randomIndex).png"
return bar
}
}
extension ViewController : UITableViewDataSource,UITableViewDelegate {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let foo = foos[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! FooTableViewCell
var bar = bars[indexPath.row]
cell.bars = bar
cell.titleLabel.text = foo.title
cell.descriptionLabel.text = foo.description
cell.delegateCollection = self
self.view.layoutIfNeeded()
cell.const_Height_CollectionView.constant = cell.iconsCollectionView.contentSize.height
self.view.layoutIfNeeded()
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return foos.count
}
}
extension ViewController : TableViewDelegate {
func cellTapped(for obj: FooTableViewCell) {
if let indexPath = tableView.indexPath(for: obj) {
bars[indexPath.row].append(getRandomItem())
self.tableView.beginUpdates()
self.tableView.reloadRows(at: [indexPath], with: .automatic)
self.tableView.endUpdates()
}
}
}
OUTPUT
EDIT / UPDATE 2
I was not aware about orientation supports and ipad support.
now when the orientation changes we have to re-layout the collection view.
So logic is
total items + 1 (+ 1 because of that plus icon )
Item Size * (total Items / 3).rounded
suppose you have 7 Items
so item size is 93 (Per row) * ( 8 / 3).rounded = 279
So here you need to manage some hardcoded values as per your requirement for iPad and Landscape mode. For now I am considering 3 objects per row same as iPhone design.
Here Hardcoded cell number is 3 You can manage your own.
Step1:
Add Following method in viewContorller.swift
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
self.tableView.beginUpdates()
self.tableView.reloadData()
self.tableView.endUpdates()
}
Replace cellForRowAtIndexPath
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let foo = foos[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! FooTableViewCell
cell.iconsCollectionView.initFlowLayout(superviewWidth: self.tableView.frame.width)
let bar = bars[indexPath.row]
cell.bars = bar
cell.titleLabel.text = foo.title
cell.descriptionLabel.text = foo.description
cell.delegateCollection = self
self.view.layoutIfNeeded()
let items:CGFloat = CGFloat(bar.count + 1)
let value = (items / 3.0).rounded(.awayFromZero)
cell.const_Height_CollectionView.constant = CGFloat((cell.iconsCollectionView.collectionViewLayout as! UICollectionViewFlowLayout).itemSize.height * value)
self.view.layoutIfNeeded()
cell.iconsCollectionView.setNeedsLayout()
return cell
}
And
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
if let footCell = cell as? FooTableViewCell {
footCell.const_Height_CollectionView.constant = footCell.iconsCollectionView.contentSize.height
self.view.layoutIfNeeded()
}
}
In TableviewCell
var bars:[Bar] = [] {
didSet {
self.iconsCollectionView.reloadData()
iconsCollectionView.setNeedsLayout()
self.layoutIfNeeded()
let items:CGFloat = CGFloat(bars.count + 1)
let value = (items / 3.0).rounded(.awayFromZero)
const_Height_CollectionView.constant = CGFloat((iconsCollectionView.collectionViewLayout as! UICollectionViewFlowLayout).itemSize.height * value)
self.layoutIfNeeded()
}
}
and
func cellTapped () {
iconsCollectionView.setNeedsLayout()
self.layoutIfNeeded()
self.setNeedsLayout()
let items:CGFloat = CGFloat(bars.count + 1)
let value = (items / 3.0).rounded(.awayFromZero)
const_Height_CollectionView.constant = CGFloat((iconsCollectionView.collectionViewLayout as! UICollectionViewFlowLayout).itemSize.height * value)
self.delegateCollection?.cellTapped(for: self)
}
这篇关于使用UITableViewAutomaticDimension使用嵌入式UICollectionView创建UITableView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!