使用UITableViewAutomaticDimension使用嵌入式UICollectionView创建UITableView [英] Making UITableView with embedded UICollectionView using UITableViewAutomaticDimension

查看:314
本文介绍了使用UITableViewAutomaticDimension使用嵌入式UICollectionView创建UITableView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个 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 =lefthorizo​​ntalHuggingPriority =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 =lefthorizo​​ntalHuggingPriority =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 horizo​​ntalHuggingPriority = 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 contentHorizo​​ntalAlignment = 右 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆