首页 > 解决方案 > 为什么 TableView 单元格中的垂直堆栈视图不能动态生成高度?

问题描述

这是一张图表,解释了我正在尝试做什么以及我所看到的:

在此处输入图像描述

将标题和支持内容放入每个单元格按预期工作,但我尝试在我的 UITableViewDataSource 委托中使用以下代码来测试是否看到颜色块进入垂直堆栈视图,但它只显示一条黄线,导致我相信垂直堆栈视图的高度根本没有增加。

我认为问题出在哪里:我将垂直堆栈视图上的约束分别设置为 0,希望底部 0 意味着它会尽可能地继续向下(即它从底部开始为 0,无论底部可能是什么)但也许这不是正确的方法,它实际上将高度限制为 0。

    let box1 = UIView()
    box1.frame = CGRect(x: 0, y: 0, width: 400, height: 400)
    box1.backgroundColor = .yellow
    let box2 = UIView()
    box2.frame = CGRect(x: 0, y: 0, width: 400, height: 400)
    box2.backgroundColor = .yellow
    cell.verticalStackView.addArrangedSubview(box1)
    cell.verticalStackView.addArrangedSubview(box2)

注意:stackview 的分布为fill equally4,间距为 4。将分布更改为fill删除黄线但不能解决。

我不知道在哪里添加UITableViewAutomaticDimension到 tableview 行高,所以也许这就是修复?

标签: iosswift

解决方案


根据评论 - 看来 OP 解决了这个问题......但是,这是一个无论如何都可能有帮助的例子。

这是单元格 xib(蓝色轮廓是堆栈视图的边界):

在此处输入图像描述

堆栈视图设置:

在此处输入图像描述

注意:为了在设计过程中满足 Interface Builder,我给堆栈视图设置了 100 的高度约束,但将其设置为占位符,以便在运行时将其删除:

在此处输入图像描述

结果:

在此处输入图像描述

向下滚动一点后:

在此处输入图像描述

这是xib的来源:

<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="15705" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
    <device id="retina6_1" orientation="portrait" appearance="light"/>
    <dependencies>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15706"/>
        <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="261" id="qNz-cd-r4O" customClass="MPCCell" customModule="MiniScratch" customModuleProvider="target">
            <rect key="frame" x="0.0" y="0.0" width="356" height="261"/>
            <autoresizingMask key="autoresizingMask"/>
            <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="qNz-cd-r4O" id="rw4-5D-vJu">
                <rect key="frame" x="0.0" y="0.0" width="356" height="261"/>
                <autoresizingMask key="autoresizingMask"/>
                <subviews>
                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="iI3-m2-L2U">
                        <rect key="frame" x="36" y="12" width="284" height="45"/>
                        <subviews>
                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Headline" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="UW8-L7-x4a">
                                <rect key="frame" x="108" y="12" width="68" height="21"/>
                                <fontDescription key="fontDescription" type="system" pointSize="17"/>
                                <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                <nil key="highlightedColor"/>
                            </label>
                        </subviews>
                        <color key="backgroundColor" red="0.26394423839999998" green="0.44803369050000003" blue="0.76730746029999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                        <constraints>
                            <constraint firstAttribute="bottom" secondItem="UW8-L7-x4a" secondAttribute="bottom" constant="12" id="09x-rj-djb"/>
                            <constraint firstItem="UW8-L7-x4a" firstAttribute="centerY" secondItem="iI3-m2-L2U" secondAttribute="centerY" id="Pjq-kb-VBD"/>
                            <constraint firstItem="UW8-L7-x4a" firstAttribute="top" secondItem="iI3-m2-L2U" secondAttribute="top" constant="12" id="sbt-LW-A1a"/>
                            <constraint firstItem="UW8-L7-x4a" firstAttribute="centerX" secondItem="iI3-m2-L2U" secondAttribute="centerX" id="tbW-Up-s9e"/>
                        </constraints>
                    </view>
                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Q2N-gq-ZWR">
                        <rect key="frame" x="36" y="65" width="284" height="44.5"/>
                        <subviews>
                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Supporting content" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="hbx-b0-ZsJ">
                                <rect key="frame" x="8" y="12" width="268" height="20.5"/>
                                <fontDescription key="fontDescription" type="system" pointSize="17"/>
                                <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                <nil key="highlightedColor"/>
                            </label>
                        </subviews>
                        <color key="backgroundColor" red="0.26394423839999998" green="0.44803369050000003" blue="0.76730746029999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                        <constraints>
                            <constraint firstItem="hbx-b0-ZsJ" firstAttribute="centerX" secondItem="Q2N-gq-ZWR" secondAttribute="centerX" id="KMe-cw-HFN"/>
                            <constraint firstItem="hbx-b0-ZsJ" firstAttribute="leading" secondItem="Q2N-gq-ZWR" secondAttribute="leading" constant="8" id="NGw-fR-eJd"/>
                            <constraint firstItem="hbx-b0-ZsJ" firstAttribute="top" secondItem="Q2N-gq-ZWR" secondAttribute="top" constant="12" id="TLL-g6-Fjq"/>
                            <constraint firstAttribute="trailing" secondItem="hbx-b0-ZsJ" secondAttribute="trailing" constant="8" id="tyG-4i-x2s"/>
                            <constraint firstItem="hbx-b0-ZsJ" firstAttribute="centerY" secondItem="Q2N-gq-ZWR" secondAttribute="centerY" id="yBl-K5-xKl"/>
                            <constraint firstAttribute="bottom" secondItem="hbx-b0-ZsJ" secondAttribute="bottom" constant="12" id="zpZ-83-jqU"/>
                        </constraints>
                    </view>
                    <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="1YZ-yV-ruW">
                        <rect key="frame" x="50" y="117.5" width="256" height="100"/>
                        <constraints>
                            <constraint firstAttribute="height" constant="100" placeholder="YES" id="GVt-mR-ILU"/>
                        </constraints>
                    </stackView>
                </subviews>
                <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                <constraints>
                    <constraint firstItem="Q2N-gq-ZWR" firstAttribute="centerX" secondItem="iI3-m2-L2U" secondAttribute="centerX" id="0X4-Z9-AJY"/>
                    <constraint firstItem="1YZ-yV-ruW" firstAttribute="centerX" secondItem="Q2N-gq-ZWR" secondAttribute="centerX" id="Ba0-yG-ibk"/>
                    <constraint firstItem="iI3-m2-L2U" firstAttribute="top" secondItem="rw4-5D-vJu" secondAttribute="top" constant="12" id="Hcr-2X-7pH"/>
                    <constraint firstItem="Q2N-gq-ZWR" firstAttribute="top" secondItem="iI3-m2-L2U" secondAttribute="bottom" constant="8" id="RGZ-1L-32E"/>
                    <constraint firstItem="1YZ-yV-ruW" firstAttribute="width" secondItem="Q2N-gq-ZWR" secondAttribute="width" multiplier="0.9" id="Rgu-ue-rwv"/>
                    <constraint firstItem="iI3-m2-L2U" firstAttribute="leading" secondItem="rw4-5D-vJu" secondAttribute="leading" constant="36" id="SWp-gQ-CmT"/>
                    <constraint firstItem="1YZ-yV-ruW" firstAttribute="top" secondItem="Q2N-gq-ZWR" secondAttribute="bottom" constant="8" id="eoV-nE-dBM"/>
                    <constraint firstAttribute="trailing" secondItem="iI3-m2-L2U" secondAttribute="trailing" constant="36" id="jB2-qc-ba0"/>
                    <constraint firstItem="Q2N-gq-ZWR" firstAttribute="width" secondItem="iI3-m2-L2U" secondAttribute="width" id="mjX-lH-QBz"/>
                    <constraint firstAttribute="bottomMargin" relation="greaterThanOrEqual" secondItem="1YZ-yV-ruW" secondAttribute="bottom" constant="8" id="okC-Kj-vYa"/>
                </constraints>
            </tableViewCellContentView>
            <connections>
                <outlet property="headlineLabel" destination="UW8-L7-x4a" id="9mT-WA-Leg"/>
                <outlet property="supportLabel" destination="hbx-b0-ZsJ" id="buT-GP-BD7"/>
                <outlet property="vertStackView" destination="1YZ-yV-ruW" id="rSG-Ln-gzU"/>
            </connections>
            <point key="canvasLocation" x="111.59420289855073" y="150.33482142857142"/>
        </tableViewCell>
    </objects>
</document>

并让表视图控制器和单元类产生该结果:

//
//  ExampleTableViewController.swift
//  Created by Don Mag on 4/13/20.
//

import UIKit

extension CGFloat {
    static func random() -> CGFloat {
        return CGFloat(arc4random()) / CGFloat(UInt32.max)
    }
}

extension UIColor {
    static func random() -> UIColor {
        return UIColor(
            red:   .random(),
            green: .random(),
            blue:  .random(),
            alpha: 1.0
        )
    }
}

struct MyCustomData {
    var headline: String = ""
    var support: String = ""
    var blockColors: [UIColor] = [UIColor]()
}

class MPCCell: UITableViewCell {

    @IBOutlet var headlineLabel: UILabel!
    @IBOutlet var supportLabel: UILabel!
    @IBOutlet var vertStackView: UIStackView!

    override func prepareForReuse() {
        super.prepareForReuse()
        // clear previously added subviews from the stack view
        vertStackView.arrangedSubviews.forEach {
            $0.removeFromSuperview()
        }
    }

    func addBlocks(_ colors: [UIColor]) -> Void {

        // for each colr
        colors.forEach {
            // create a view
            let v = UIView()
            // set its background
            v.backgroundColor = $0
            // give view a height constraint, but set its
            //  priority to 999 (prevents auto-layout warnings)
            let c = v.heightAnchor.constraint(equalToConstant: 80.0)
            c.priority = UILayoutPriority(rawValue: 999)
            c.isActive = true
            // add it to the stack view
            vertStackView.addArrangedSubview(v)
        }

    }

}

class ExampleTableViewController: UITableViewController {

    var myData: [MyCustomData] = [MyCustomData]()

    override func viewDidLoad() {
        super.viewDidLoad()

        // lets just create a sample data set
        // 15 rows, with varying number of random-color "blocks"
        // to add to the cell's stack view

        let numBlocks: [Int] = [2, 3, 2, 5, 4]

        for i in 0..<15 {
            var d = MyCustomData()
            d.headline = "Headline \(i + 1)"
            d.support = "Supporting content \(i + 1)"
            if i % 3 == 1 {
                d.support += " - every third row will have more text here, so we can demonstrate auto-height when word wrapping."
            }
            var colors: [UIColor] = [UIColor]()
            for _ in 0..<numBlocks[i % numBlocks.count] {
                colors.append(.random())
            }
            d.blockColors = colors
            myData.append(d)
        }

        let nib = UINib(nibName: "MPCCell", bundle: nil)
        tableView.register(nib, forCellReuseIdentifier: "MPCCell")

    }

    // MARK: - Table view data source

    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    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: "MPCCell", for: indexPath) as! MPCCell

        let d = myData[indexPath.row]

        cell.headlineLabel.text = d.headline
        cell.supportLabel.text = d.support
        cell.addBlocks(d.blockColors)

        return cell
    }

}

推荐阅读