UItableView单元格自动调整大小

发布于 2025-01-13 08:26:59 字数 521 浏览 2 评论 0原文

我几乎整整一周都在尝试解决这个问题,我试图实现一个表格单元格,其中有 5 个静态参数和 3 个浮动参数(它们的大小可以更大或更小,它们也可能根本不存在) ),我无法弄清楚这三个参数,我试图隐藏该元素,但这一切都是徒劳的,因为重用一切都会中断。某处高度较高,某处高度较低。我该如何解决这个问题?也许使用不同类型的细胞对我来说更容易?这是我的布局,我所说的是 3 个彩色元素。目前,它们中的每一个都将距离最近的元素(stackview 和内部元素)的约束设置为 0,并且高度大于或等于。预先感谢

UIStackView 布局

布局

它有什么作用真的很像

I've been trying to solve this problem for almost a whole week, im trying to implement a table cell in which there are 5 static parameters, and 3 floating ones (their sizes can be larger or smaller, they may also not exist at all), I can't figure out these three parameters, I'm trying to hide the element, but that's all in vain, because of reuse everything breaks. Somewhere the height is more, somewhere less. How can I resolve this issue? Maybe it's easier for me to use different types of cells? here is my layout, 3 multicolored elements is what i am talking about. At the moment, each of them has constraints set to 0 to the nearest element (stackview and elements inside) and a height greater than or equal to. Thanks in advance

UIStackView Layout

layout

what does it really look like

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

死开点丶别碍眼 2025-01-20 08:26:59

看起来您有很多事情要做,这可能应该是几个不同的问题,但这里有一些评论...

首先,您说您的堆栈视图元素将最近元素的约束设置为 0 ...您应该允许堆栈视图来布局元素 - 您不应该添加元素间约束。

其次,堆栈视图的一大好处是,如果您隐藏一个元素,它所占用的空间就会被删除。

因此,如果您的“中间”元素是多行标签 - 我将其称为 redLabel - 并且您设置了 redLabel.isHidden = true,您的堆栈视图就可以了这个:

在此处输入图像描述

如果您还在底部元素(集合视图?)上设置 .isHidden = true,它将执行以下操作:

在此处输入图像描述< /a>

我打了一起提供一个可能对您有所帮助的简单示例。运行时看起来像这样(青色是文本视图,红色是标签,灰色矩形是集合视图单元格):

在此处输入图像描述

对于前 3 行,所有 3 个元素都有数据(因此它们是可见的) )。向下滚动,我们显示没有红色标签的第 3 行,没有集合视图的第 4 行,以及隐藏的第 5 行:

在此处输入图像描述

文本视图已禁用滚动,因此它将自行调整大小:

<一个href="https://i.sstatic.net/BnsRD.png" rel="nofollow noreferrer">在此处输入图像描述

当用户输入:

在此处输入图像描述


这是 SizingCell.xib 的源代码:

<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
    <device id="retina6_1" orientation="portrait" appearance="light"/>
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
        <capability name="System colors in document resources" minToolsVersion="11.0"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <objects>
        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
        <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="238" id="61P-bN-2e0" customClass="SizingCell" customModule="SWiOS12" customModuleProvider="target">
            <rect key="frame" x="0.0" y="0.0" width="414" height="238"/>
            <autoresizingMask key="autoresizingMask"/>
            <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="61P-bN-2e0" id="huS-tm-qA9">
                <rect key="frame" x="0.0" y="0.0" width="414" height="238"/>
                <autoresizingMask key="autoresizingMask"/>
                <subviews>
                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="1000" text="Title Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="XQI-LW-mKN">
                        <rect key="frame" x="20" y="11" width="79" height="20.5"/>
                        <color key="backgroundColor" red="0.45009386540000001" green="0.98132258650000004" blue="0.4743030667" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                        <fontDescription key="fontDescription" type="system" pointSize="17"/>
                        <nil key="textColor"/>
                        <nil key="highlightedColor"/>
                    </label>
                    <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="2" translatesAutoresizingMaskIntoConstraints="NO" id="bt1-hr-iCP">
                        <rect key="frame" x="20" y="39.5" width="374" height="187.5"/>
                        <subviews>
                            <textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" verticalHuggingPriority="1000" scrollEnabled="NO" text="This is the text view" textAlignment="natural" translatesAutoresizingMaskIntoConstraints="NO" id="laq-Mt-rKJ">
                                <rect key="frame" x="0.0" y="0.0" width="374" height="37.5"/>
                                <color key="backgroundColor" red="0.45138680930000002" green="0.99309605359999997" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                <color key="textColor" systemColor="labelColor"/>
                                <fontDescription key="fontDescription" type="system" pointSize="18"/>
                                <textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
                            </textView>
                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" text="Multiline Label - may be here or not." textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="JUe-Ch-kcB">
                                <rect key="frame" x="0.0" y="39.5" width="374" height="86"/>
                                <color key="backgroundColor" red="1" green="0.7552904054556101" blue="0.70372087555305396" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                <fontDescription key="fontDescription" type="system" pointSize="17"/>
                                <nil key="textColor"/>
                                <nil key="highlightedColor"/>
                            </label>
                            <collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="none" translatesAutoresizingMaskIntoConstraints="NO" id="XmM-Li-1e9">
                                <rect key="frame" x="0.0" y="127.5" width="374" height="60"/>
                                <color key="backgroundColor" systemColor="systemBackgroundColor"/>
                                <constraints>
                                    <constraint firstAttribute="height" constant="60" id="ggu-r1-slr"/>
                                </constraints>
                                <collectionViewFlowLayout key="collectionViewLayout" scrollDirection="horizontal" minimumLineSpacing="10" minimumInteritemSpacing="10" id="1gL-6N-ttm">
                                    <size key="itemSize" width="128" height="60"/>
                                    <size key="estimatedItemSize" width="128" height="60"/>
                                    <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>
                            </collectionView>
                        </subviews>
                    </stackView>
                </subviews>
                <constraints>
                    <constraint firstItem="bt1-hr-iCP" firstAttribute="leading" secondItem="huS-tm-qA9" secondAttribute="leadingMargin" id="31M-SL-LEh"/>
                    <constraint firstItem="XQI-LW-mKN" firstAttribute="top" secondItem="huS-tm-qA9" secondAttribute="topMargin" id="AoR-ds-v7X"/>
                    <constraint firstItem="bt1-hr-iCP" firstAttribute="top" secondItem="XQI-LW-mKN" secondAttribute="bottom" constant="8" id="PfP-ND-eWY"/>
                    <constraint firstItem="XQI-LW-mKN" firstAttribute="leading" secondItem="huS-tm-qA9" secondAttribute="leadingMargin" id="qbq-Gq-k7L"/>
                    <constraint firstAttribute="trailingMargin" secondItem="bt1-hr-iCP" secondAttribute="trailing" id="tqQ-o4-hue"/>
                    <constraint firstAttribute="bottomMargin" secondItem="bt1-hr-iCP" secondAttribute="bottom" priority="750" id="uS0-q9-D7w"/>
                </constraints>
            </tableViewCellContentView>
            <connections>
                <outlet property="collectionView" destination="XmM-Li-1e9" id="ks1-BH-srH"/>
                <outlet property="redLabel" destination="JUe-Ch-kcB" id="Lqn-bA-jsh"/>
                <outlet property="textView" destination="laq-Mt-rKJ" id="rx6-zp-jVB"/>
                <outlet property="titleLabel" destination="XQI-LW-mKN" id="k6X-B0-Slx"/>
            </connections>
            <point key="canvasLocation" x="305.79710144927537" y="113.83928571428571"/>
        </tableViewCell>
    </objects>
    <resources>
        <systemColor name="labelColor">
            <color white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
        </systemColor>
        <systemColor name="systemBackgroundColor">
            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
        </systemColor>
    </resources>
</document>

这是生成这些屏幕截图的源代码:

struct MyStruct {
    var titleString: String = ""
    var textViewString: String?
    var redLabelString: String?
    var collectionViewData: [String]?
}

class MyCollectionViewCell: UICollectionViewCell {
    let label = UILabel()
    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }
    func commonInit() {
        label.textAlignment = .center
        label.translatesAutoresizingMaskIntoConstraints = false
        contentView.addSubview(label)
        let g = contentView.layoutMarginsGuide
        // this prevents auto-layout complaints
        let cWidth = label.widthAnchor.constraint(greaterThanOrEqualToConstant: 50.0)
        cWidth.priority = .required - 1
        NSLayoutConstraint.activate([
            label.centerYAnchor.constraint(equalTo: g.centerYAnchor),
            label.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 12.0),
            label.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -12.0),
            cWidth,
        ])
        label.backgroundColor = .yellow
        contentView.backgroundColor = .lightGray
    }
}

class SizingCell: UITableViewCell, UITextViewDelegate, UICollectionViewDataSource, UICollectionViewDelegate {
    
    var editCallback: ((UITableViewCell, String) -> ())?
    
    var cvData: [String] = []
    
    @IBOutlet var titleLabel: UILabel!
    
    @IBOutlet var textView: UITextView!
    @IBOutlet var redLabel: UILabel!
    @IBOutlet var collectionView: UICollectionView!
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        commonInit()
    }
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }
    override func awakeFromNib() {
        super.awakeFromNib()
        commonInit()
    }
    func commonInit() {
        if collectionView != nil {
            collectionView.register(MyCollectionViewCell.self, forCellWithReuseIdentifier: "myC")
            collectionView.delegate = self
            collectionView.dataSource = self
            
            textView.delegate = self
        }
    }
    func fillData(_ st: MyStruct) {
        titleLabel.text = st.titleString
        
        textView.text = st.textViewString
        
        if let s = st.redLabelString {
            redLabel.text = s
        }
        // hide the red label if it has no text
        redLabel.isHidden = st.redLabelString == nil

        // if st HAS data, do your collection view setup here
        if let d = st.collectionViewData {
            cvData = d
        } else {
            cvData = []
        }
        // hide the collection view if there is no data
        collectionView.isHidden = st.collectionViewData == nil
        
    }
    
    func textViewDidChange(_ textView: UITextView) {
        // tell the controller the textView was edited
        editCallback?(self, textView.text)
    }
    
    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return cvData.count
    }
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "myC", for: indexPath) as! MyCollectionViewCell
        cell.label.text = cvData[indexPath.item]
        return cell
    }
    
}

class TestSizingCellTableViewController: UITableViewController {
    
    var myData: [MyStruct] = []
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // create some sample data
        let sampleStrings: [String] = [
            "Short string.",
            "This is a longer string.",
            "This string should be long enough that we'll get word-wrapping.",
        ]
        let sampelData: [[String]] = [
            ["1", "2", "3", "4"],
            ["A", "B", "C - dynamic width cells", "D", "E", "F", "G"],
            ["One", "Two", "Three", "Four - wider", "Five", "Six", "Seven - wider", "Eight", "Nine", "Ten"],
        ]
        
        for i in 0..<10 {
            var st = MyStruct()
            st.titleString = "Row \(i)"
            st.textViewString = "Text View \(i): " + sampleStrings[i % sampleStrings.count]
            st.redLabelString = "Red Label \(i): " + sampleStrings[i % sampleStrings.count]
            st.collectionViewData = sampelData[i % sampelData.count]
            myData.append(st)
        }
        
        // let's remove the redLabel text for the 4th row (Row 3)
        myData[3].textViewString = "Red Label will be gone!"
        myData[3].redLabelString = nil

        // let's remove the collection view for the 5th row (Row 4)
        myData[4].redLabelString = "Red Label has text again, so we see it, but collection view will be gone."
        myData[4].collectionViewData = nil
        
        // let's remove both the redLabel and the collection view for the 6th row (Row 5)
        myData[5].textViewString = "Both Red Label and Collection View will be gone!"
        myData[5].redLabelString = nil
        myData[5].collectionViewData = nil
        
        tableView.register(UINib(nibName: "SizingCell", bundle: nil), forCellReuseIdentifier: "sizingCell")
        
    }
    
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return myData.count
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "sizingCell", for: indexPath) as! SizingCell
        cell.fillData(myData[indexPath.row])
        cell.editCallback = { [weak self] c, s in
            guard let self = self,
                  let idxPath = self.tableView.indexPath(for: c)
            else { return }
            self.myData[idxPath.row].textViewString = s
            self.tableView.performBatchUpdates(nil, completion: nil)
        }
        return cell
    }
    
}

It looks like you have a lot going on, and this should probably be a couple different questions, but here are some comments...

First, you said your stack view elements have constraints set to 0 to the nearest element ... you should allow the stack view to layout the elements - you should not be adding inter-element constraints.

Second, one of the big benefits of a stack view is that if you hide an element, the space it has taken is removed.

So, if your "middle" element is a multi-line label - I'll call it redLabel - and you set redLabel.isHidden = true, your stack view will do this:

enter image description here

If you then also set .isHidden = true on your bottom element (the collection view?), it will do this:

enter image description here

I slapped together a quick example that may help you on your way. It looks like this when running (cyan is the textView, red is a label, gray rects are the collection view cells):

enter image description here

For the first 3 rows, all 3 elements have data (so they are visible). Scrolling down, we show Row 3 without the red label, Row 4 without the collection view, and Row 5 with both of them hidden:

enter image description here

The text view has scrolling disabled, so it will size itself:

enter image description here

as the user types:

enter image description here


This is the source for SizingCell.xib:

<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
    <device id="retina6_1" orientation="portrait" appearance="light"/>
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
        <capability name="System colors in document resources" minToolsVersion="11.0"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <objects>
        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
        <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="238" id="61P-bN-2e0" customClass="SizingCell" customModule="SWiOS12" customModuleProvider="target">
            <rect key="frame" x="0.0" y="0.0" width="414" height="238"/>
            <autoresizingMask key="autoresizingMask"/>
            <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="61P-bN-2e0" id="huS-tm-qA9">
                <rect key="frame" x="0.0" y="0.0" width="414" height="238"/>
                <autoresizingMask key="autoresizingMask"/>
                <subviews>
                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="1000" text="Title Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="XQI-LW-mKN">
                        <rect key="frame" x="20" y="11" width="79" height="20.5"/>
                        <color key="backgroundColor" red="0.45009386540000001" green="0.98132258650000004" blue="0.4743030667" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                        <fontDescription key="fontDescription" type="system" pointSize="17"/>
                        <nil key="textColor"/>
                        <nil key="highlightedColor"/>
                    </label>
                    <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="2" translatesAutoresizingMaskIntoConstraints="NO" id="bt1-hr-iCP">
                        <rect key="frame" x="20" y="39.5" width="374" height="187.5"/>
                        <subviews>
                            <textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" verticalHuggingPriority="1000" scrollEnabled="NO" text="This is the text view" textAlignment="natural" translatesAutoresizingMaskIntoConstraints="NO" id="laq-Mt-rKJ">
                                <rect key="frame" x="0.0" y="0.0" width="374" height="37.5"/>
                                <color key="backgroundColor" red="0.45138680930000002" green="0.99309605359999997" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                <color key="textColor" systemColor="labelColor"/>
                                <fontDescription key="fontDescription" type="system" pointSize="18"/>
                                <textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
                            </textView>
                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" text="Multiline Label - may be here or not." textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="JUe-Ch-kcB">
                                <rect key="frame" x="0.0" y="39.5" width="374" height="86"/>
                                <color key="backgroundColor" red="1" green="0.7552904054556101" blue="0.70372087555305396" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                <fontDescription key="fontDescription" type="system" pointSize="17"/>
                                <nil key="textColor"/>
                                <nil key="highlightedColor"/>
                            </label>
                            <collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="none" translatesAutoresizingMaskIntoConstraints="NO" id="XmM-Li-1e9">
                                <rect key="frame" x="0.0" y="127.5" width="374" height="60"/>
                                <color key="backgroundColor" systemColor="systemBackgroundColor"/>
                                <constraints>
                                    <constraint firstAttribute="height" constant="60" id="ggu-r1-slr"/>
                                </constraints>
                                <collectionViewFlowLayout key="collectionViewLayout" scrollDirection="horizontal" minimumLineSpacing="10" minimumInteritemSpacing="10" id="1gL-6N-ttm">
                                    <size key="itemSize" width="128" height="60"/>
                                    <size key="estimatedItemSize" width="128" height="60"/>
                                    <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>
                            </collectionView>
                        </subviews>
                    </stackView>
                </subviews>
                <constraints>
                    <constraint firstItem="bt1-hr-iCP" firstAttribute="leading" secondItem="huS-tm-qA9" secondAttribute="leadingMargin" id="31M-SL-LEh"/>
                    <constraint firstItem="XQI-LW-mKN" firstAttribute="top" secondItem="huS-tm-qA9" secondAttribute="topMargin" id="AoR-ds-v7X"/>
                    <constraint firstItem="bt1-hr-iCP" firstAttribute="top" secondItem="XQI-LW-mKN" secondAttribute="bottom" constant="8" id="PfP-ND-eWY"/>
                    <constraint firstItem="XQI-LW-mKN" firstAttribute="leading" secondItem="huS-tm-qA9" secondAttribute="leadingMargin" id="qbq-Gq-k7L"/>
                    <constraint firstAttribute="trailingMargin" secondItem="bt1-hr-iCP" secondAttribute="trailing" id="tqQ-o4-hue"/>
                    <constraint firstAttribute="bottomMargin" secondItem="bt1-hr-iCP" secondAttribute="bottom" priority="750" id="uS0-q9-D7w"/>
                </constraints>
            </tableViewCellContentView>
            <connections>
                <outlet property="collectionView" destination="XmM-Li-1e9" id="ks1-BH-srH"/>
                <outlet property="redLabel" destination="JUe-Ch-kcB" id="Lqn-bA-jsh"/>
                <outlet property="textView" destination="laq-Mt-rKJ" id="rx6-zp-jVB"/>
                <outlet property="titleLabel" destination="XQI-LW-mKN" id="k6X-B0-Slx"/>
            </connections>
            <point key="canvasLocation" x="305.79710144927537" y="113.83928571428571"/>
        </tableViewCell>
    </objects>
    <resources>
        <systemColor name="labelColor">
            <color white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
        </systemColor>
        <systemColor name="systemBackgroundColor">
            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
        </systemColor>
    </resources>
</document>

and this is the source code that produced those screen-caps:

struct MyStruct {
    var titleString: String = ""
    var textViewString: String?
    var redLabelString: String?
    var collectionViewData: [String]?
}

class MyCollectionViewCell: UICollectionViewCell {
    let label = UILabel()
    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }
    func commonInit() {
        label.textAlignment = .center
        label.translatesAutoresizingMaskIntoConstraints = false
        contentView.addSubview(label)
        let g = contentView.layoutMarginsGuide
        // this prevents auto-layout complaints
        let cWidth = label.widthAnchor.constraint(greaterThanOrEqualToConstant: 50.0)
        cWidth.priority = .required - 1
        NSLayoutConstraint.activate([
            label.centerYAnchor.constraint(equalTo: g.centerYAnchor),
            label.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 12.0),
            label.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -12.0),
            cWidth,
        ])
        label.backgroundColor = .yellow
        contentView.backgroundColor = .lightGray
    }
}

class SizingCell: UITableViewCell, UITextViewDelegate, UICollectionViewDataSource, UICollectionViewDelegate {
    
    var editCallback: ((UITableViewCell, String) -> ())?
    
    var cvData: [String] = []
    
    @IBOutlet var titleLabel: UILabel!
    
    @IBOutlet var textView: UITextView!
    @IBOutlet var redLabel: UILabel!
    @IBOutlet var collectionView: UICollectionView!
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        commonInit()
    }
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }
    override func awakeFromNib() {
        super.awakeFromNib()
        commonInit()
    }
    func commonInit() {
        if collectionView != nil {
            collectionView.register(MyCollectionViewCell.self, forCellWithReuseIdentifier: "myC")
            collectionView.delegate = self
            collectionView.dataSource = self
            
            textView.delegate = self
        }
    }
    func fillData(_ st: MyStruct) {
        titleLabel.text = st.titleString
        
        textView.text = st.textViewString
        
        if let s = st.redLabelString {
            redLabel.text = s
        }
        // hide the red label if it has no text
        redLabel.isHidden = st.redLabelString == nil

        // if st HAS data, do your collection view setup here
        if let d = st.collectionViewData {
            cvData = d
        } else {
            cvData = []
        }
        // hide the collection view if there is no data
        collectionView.isHidden = st.collectionViewData == nil
        
    }
    
    func textViewDidChange(_ textView: UITextView) {
        // tell the controller the textView was edited
        editCallback?(self, textView.text)
    }
    
    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return cvData.count
    }
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "myC", for: indexPath) as! MyCollectionViewCell
        cell.label.text = cvData[indexPath.item]
        return cell
    }
    
}

class TestSizingCellTableViewController: UITableViewController {
    
    var myData: [MyStruct] = []
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // create some sample data
        let sampleStrings: [String] = [
            "Short string.",
            "This is a longer string.",
            "This string should be long enough that we'll get word-wrapping.",
        ]
        let sampelData: [[String]] = [
            ["1", "2", "3", "4"],
            ["A", "B", "C - dynamic width cells", "D", "E", "F", "G"],
            ["One", "Two", "Three", "Four - wider", "Five", "Six", "Seven - wider", "Eight", "Nine", "Ten"],
        ]
        
        for i in 0..<10 {
            var st = MyStruct()
            st.titleString = "Row \(i)"
            st.textViewString = "Text View \(i): " + sampleStrings[i % sampleStrings.count]
            st.redLabelString = "Red Label \(i): " + sampleStrings[i % sampleStrings.count]
            st.collectionViewData = sampelData[i % sampelData.count]
            myData.append(st)
        }
        
        // let's remove the redLabel text for the 4th row (Row 3)
        myData[3].textViewString = "Red Label will be gone!"
        myData[3].redLabelString = nil

        // let's remove the collection view for the 5th row (Row 4)
        myData[4].redLabelString = "Red Label has text again, so we see it, but collection view will be gone."
        myData[4].collectionViewData = nil
        
        // let's remove both the redLabel and the collection view for the 6th row (Row 5)
        myData[5].textViewString = "Both Red Label and Collection View will be gone!"
        myData[5].redLabelString = nil
        myData[5].collectionViewData = nil
        
        tableView.register(UINib(nibName: "SizingCell", bundle: nil), forCellReuseIdentifier: "sizingCell")
        
    }
    
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return myData.count
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "sizingCell", for: indexPath) as! SizingCell
        cell.fillData(myData[indexPath.row])
        cell.editCallback = { [weak self] c, s in
            guard let self = self,
                  let idxPath = self.tableView.indexPath(for: c)
            else { return }
            self.myData[idxPath.row].textViewString = s
            self.tableView.performBatchUpdates(nil, completion: nil)
        }
        return cell
    }
    
}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文