使用 UITableViewAutomaticDimension 制作带有嵌入式 UICollectionView 的 UITableView [英] Making UITableView with embedded UICollectionView using UITableViewAutomaticDimension

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

问题描述

我想使用 UITableViewAutomaticDimension 创建一个带有标题标签的 UITableView 和嵌入的 UICollectionView(知道它的大小)和一些图标.问题是当我有 UICollectionView 时,UITableView 在计算单元格高度时出现问题.我必须滚动 UITableView 才能重新计算大小.但即便如此,它也存在高度问题(如果从较大的高度重复使用它太大了).最重要的是 UICollectionView 内的图标从乞讨中不知道,但它们旨在从服务器加载.

我还尝试为 UICollectionView 创建高度约束,但这样我得到无法同时满足约束",这是由于与 UIView-Encapsulated-Layout 冲突而导致的-Height 反正我自己的约束被移除了.

我已经创建了一个带有示例项目的 GitHub 存储库(我做得尽可能简单):

这是输出

希望对你有帮助

编辑/更新

您的演示项目中有很多问题.我对你的演示项目做了很多改动.

XML 复制并粘贴到情节提要中.

别忘了连接高度约束

这里是完整的故事板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"><设备id="retina4_7"orientation="portrait"><适应 id="全屏"/></设备><依赖关系><部署标识符="iOS"/><plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/><capability name="安全区域布局指南" minToolsVersion="9.0"/><capability name="Xcode 8 格式保存的文档" minToolsVersion="8.0"/></依赖关系><场景><!--查看控制器--><场景场景ID="tne-QT-ifu"><对象><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"/><子视图><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"/><原型><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"/><子视图><label opaque="NO" userInteractionEnabled="NO" contentMode="left" Horizo​​ntalHuggingPriority="251" verticalHuggingPriority="251" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit=NO"翻译AutoresizingMaskIntoConstraints="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 opaque="NO" userInteractionEnabled="NO" contentMode="left" Horizo​​ntalHuggingPriority="251" verticalHuggingPriority="251" text="Description" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit=NO"翻译AutoresizingMaskIntoConstraints="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"/></标签><collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="prototypes" translatesAutoresizingMaskIntoConstraints="NO" id="6sQ-gf-Y6x" customClass="IconsCollectionView" customModule="CollectionViewInTableView" customModuleProvider="目标"><rect key="frame" x="8" y="65" width="359" height="92.5"/><color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/><约束><约束 firstAttribute="height" 关系="greaterThanOrEqual" priority="750" constant="88" id="f9g-Du-pYg"/></约束><collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="10" minimumInteritemSpacing="10" id="Nts-Lf-FPD">

FOOTableviewCell.swift

协议 TableViewDelegate {func cellTapped (for:FooTableViewCell)}类 FooTableViewCell: UITableViewCell {静态让 singleCellHeight = 88;@IBOutlet 弱变量标题标签:UILabel!@IBOutlet 弱变量描述标签:UILabel!@IBOutlet 弱 var iconsCollectionView:IconsCollectionView!@IBOutlet 弱变量 const_Height_CollectionView:NSLayoutConstraint!var delegateCollection:TableViewDelegate?可变酒吧:[酒吧] = [] {设置{self.iconsCollectionView.reloadData()图标CollectionView.setNeedsLayout()self.layoutIfNeeded()const_Height_CollectionView.constant = iconsCollectionView.contentSize.heightself.layoutIfNeeded()}}覆盖 func awakeFromNib() {iconsCollectionView.translatesAutoresizingMaskIntoConstraints = falseiconsCollectionView.initFlowLayout(superviewWidth: self.frame.width)图标CollectionView.setNeedsLayout()图标CollectionView.dataSource = self图标CollectionView.delegate = selfconst_Height_CollectionView.constant = iconsCollectionView.contentSize.heightself.layoutIfNeeded()self.setNeedsLayout()}func cellTapped () {图标CollectionView.setNeedsLayout()self.layoutIfNeeded()self.setNeedsLayout()const_Height_CollectionView.constant = iconsCollectionView.contentSize.heightself.delegateCollection?.cellTapped(for: self)}}扩展 FooTableViewCell : UICollectionViewDataSource {func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) ->诠释{返回 bar.count + 1}func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) ->UICollectionViewCell {让 cell = collectionView.dequeueReusableCell(withReuseIdentifier: "item", for: indexPath) as!BarCollectionViewCell让行 = indexPath.row如果(行> = bar.count){cell.iconImageView.image = UIImage(named: "add.png")返回单元格} 别的 {让酒吧 = 酒吧 [行]cell.iconImageView.image = UIImage(命名:bar.imageName)打印(bar.imageName)返回单元格}}}扩展 FooTableViewCell : UICollectionViewDelegate {func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {//取消选择项(在:indexPath,动画:真)if(indexPath.row >= bars.count) {//这是一个加号按钮self.delegateCollection?.cellTapped(for: self)}}}

IconCollectionView.swift

导入 UIKit类 IconsCollectionView: DynamicCollectionView {var columnLayout:ColumnFlowLayout?覆盖 func awakeFromNib() {}func initFlowLayout(superviewWidth:CGFloat) {让布局 = ColumnFlowLayout(细胞每行:4,超级视图宽度:超级视图宽度,minimumInteritemSpacing: 0,最小行间距:0,sectionInset:UIEdgeInsets(顶部:0,左侧:0,底部:0,右侧:0))columnLayout = 布局collectionViewLayout = 布局}}

ViewController.Swift

导入 UIKit类视图控制器:UIViewController {@IBOutlet 弱 var tableView:UITableView!var foos:[Foo] = []var 酒吧:[[酒吧]] = [[]]覆盖 func viewDidLoad() {super.viewDidLoad()tableView.dataSource = 自我tableView.delegate = 自我tableView.estimatedRowHeight = 188tableView.rowHeight = UITableViewAutomaticDimensionfor i in stride(from: 1, to: 10, by: 1) {让 foo = Foo()foo.title = "项目(i)"foo.description = "描述 (i)"foos.append(foo)}bar.removeAll()对于 _ in 0 ..<foos.count {bar.append(self.loadIconsSync())}}函数 loadIconsSync() ->[酒吧] {var barObjects :[Bar] = []让 iconsCount = Utils.rnd(3, 8)for _ in stride(from: 1, to: iconsCount, by: 1) {barObjects.append(self.getRandomItem())}返回 barObjects}func getRandomItem() ->酒吧 {让 randomIndex = Utils.rnd(1, 10)让 bar = Bar()bar.imageName = "icon_(randomIndex).png"返回栏}}扩展 ViewController : UITableViewDataSource,UITableViewDelegate {func tableView(_tableView: UITableView, cellForRowAt indexPath: IndexPath) ->UITableViewCell {让 foo = foos[indexPath.row]让 cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as!FooTableViewCellvar bar = bar[indexPath.row]cell.bars = 酒吧cell.titleLabel.text = foo.titlecell.descriptionLabel.text = foo.descriptioncell.delegateCollection = 自我self.view.layoutIfNeeded()cell.const_Height_CollectionView.constant = cell.iconsCollectionView.contentSize.heightself.view.layoutIfNeeded()返回单元格}func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) ->诠释{返回 foos.count}}扩展视图控制器:TableViewDelegate {func cellTapped(for obj: FooTableViewCell) {if let indexPath = tableView.indexPath(for: obj) {bar[indexPath.row].append(getRandomItem())self.tableView.beginUpdates()self.tableView.reloadRows(at: [indexPath], with: .automatic)self.tableView.endUpdates()}}}

输出

编辑/更新 2

我不知道方向支持和 ipad 支持.

现在,当方向改变时,我们必须重新布局集合视图.

所以逻辑是

项目总数 + 1(+ 1 因为那个加号图标)

项目大小 *(项目总数/3).rounded

假设你有 7 个项目

所以项目大小为 93(每行)* ( 8/3).rounded = 279

因此,您需要根据 iPad 和横向模式的要求管理一些硬编码值.现在我正在考虑每行 3 个对象,与 iPhone 设计相同.

这里硬编码的单元格数是3,你可以自己管理.

第一步:

在 viewContorller.swift 中添加 Follow 方法

override func viewWillTransition(to size: CGSize, with coordinator: 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 {让 foo = foos[indexPath.row]让 cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as!FooTableViewCellcell.iconsCollectionView.initFlowLayout(superviewWidth: self.tableView.frame.width)让 bar = bar[indexPath.row]cell.bars = 酒吧cell.titleLabel.text = foo.titlecell.descriptionLabel.text = foo.descriptioncell.delegateCollection = 自我self.view.layoutIfNeeded()让项目:CGFloat = CGFloat(bar.count + 1)让值 = (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()返回单元格}

还有

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {如果让footCell = cell as?FooTableViewCell {footCell.const_Height_CollectionView.constant = footCell.iconsCollectionView.contentSize.heightself.view.layoutIfNeeded()}}

在 TableviewCell 中

var bar:[Bar] = [] {设置{self.iconsCollectionView.reloadData()图标CollectionView.setNeedsLayout()self.layoutIfNeeded()让项目:CGFloat = CGFloat(bars.count + 1)让值 = (items/3.0).rounded(.awayFromZero)const_Height_CollectionView.constant = CGFloat((iconsCollectionView.collectionViewLayout as!UICollectionViewFlowLayout).itemSize.height * value)self.layoutIfNeeded()}}

func cellTapped () {图标CollectionView.setNeedsLayout()self.layoutIfNeeded()self.setNeedsLayout()让项目:CGFloat = CGFloat(bars.count + 1)让值 = (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天全站免登陆