如何在 Swift 中使用两个 TableView 设计动态布局

Posted

技术标签:

【中文标题】如何在 Swift 中使用两个 TableView 设计动态布局【英文标题】:How to design a dynamic layout with two TableViews in Swift 【发布时间】:2019-03-08 13:27:47 【问题描述】:

各位程序员们好。

我花了很多时间尝试在 Swift 中设计这种布局,但收效甚微。

Drawing of the layout

这个想法是有两个 TableView:

顶部的一个,有零个或多个(未定义)单元格,不能滚动,并且它的高度随着单元格的数量而增长。 底部有零个或多个(未定义)单元格,可滚动,因此其高度适应后一个表格视图留下的空间。

我已经尝试以编程方式使用约束,方法是将两个表顶部约束设置到屏幕顶部,然后根据顶部 TableView 的大小修改该约束。好像没用。

我还尝试根据将要绘制的单元格数量以编程方式修改表格的高度。也没用。

老实说,我现在正处于一个死胡同,我正在寻求帮助或一些新的想法来让它发挥作用。任何帮助将不胜感激。提前致谢!

【问题讨论】:

在界面构建器中使用约束。将第二个表设置为第一个表下的前0。 很难以编程方式提供约束。必须以编程方式提供约束? @user3344236 问题是通过使用界面生成器设置约束,我需要为顶部表格设置固定高度。我需要它动态增长。 不,你可以用其他方式。添加一个@IBOutlet 弱变量dynamicHEIGHT:NSLayoutConstraint!在你的课上。然后在界面生成器中为您的表格设置一个固定高度。然后采用该高度约束并将其与 dynamicHEIGHT 链接。然后在您的代码中,您可以根据自己的意愿操纵此高度,如 dynamicHEIGHT.constant = yourarray.count * 所需的行高度 ... 其中 yourarray 是您为第一个 tableview 拥有的数据源。这样,即使您增加第一个表视图(行)中的元素数量,第二个表仍然会排在第一位 代替两个表格视图,您可以创建两个表格视图单元格,每个单元格都包含一个表格视图。比这很容易:) 【参考方案1】:

您需要决定一些额外的逻辑 - 例如,当顶部表格视图中有太多行时该怎么办,但这是一种方法:

使用这个自定义表格视图类(来自https://***.com/a/48623673/6257435):

final class ContentSizedTableView: UITableView 
    override var contentSize:CGSize 
        didSet 
            invalidateIntrinsicContentSize()
        
    

    override var intrinsicContentSize: CGSize 
        layoutIfNeeded()
        return CGSize(width: UIView.noIntrinsicMetric, height: contentSize.height)
    

每当内容大小发生变化时,这将“自动调整”您的表格视图。要使用它,请添加一个表格视图并将其类设置为ContentSizedTableView

根据需要限制顶部、前导和尾随。 将底部限制到底部表格视图的顶部。 给它一个高度限制 - 什么都没关系,但是使用200 让您可以使用布局。但是...编辑该高度限制并选中 Placeholder - Remove at build time 复选框。 根据需要将底部表格视图限制为前导、尾随和底部。

现在,当您向top table view 添加行时,它将自动垂直扩展,而bottom table view 将自动垂直收缩(直到它消失)。因为top table view底部 仍被限制在bottom table view顶部top table view 将停止增长并可以滚动(而不是从视图的底部)。

这是一个非常简单的例子:

import UIKit

final class ContentSizedTableView: UITableView 
    override var contentSize:CGSize 
        didSet 
            invalidateIntrinsicContentSize()
        
    

    override var intrinsicContentSize: CGSize 
        layoutIfNeeded()
        return CGSize(width: UIView.noIntrinsicMetric, height: contentSize.height)
    


class SimpleTopCell: UITableViewCell 

    @IBOutlet var theLabel: UILabel!



class SimpleBottomCell: UITableViewCell 

    @IBOutlet var theLabel: UILabel!




class AutoSizeTableViewController: UIViewController, UITableViewDataSource, UITableViewDelegate 

    @IBOutlet var topTableView: ContentSizedTableView!

    @IBOutlet var bottomTableView: UITableView!

    var numRowsTop = 8
    var numRowsBottom = 12

    override func viewDidLoad() 
        super.viewDidLoad()

        topTableView.dataSource = self
        bottomTableView.dataSource = self

        topTableView.delegate = self
        bottomTableView.delegate = self

    

    @IBAction func addRowTapped(_ sender: Any) 
        numRowsTop += 1
        topTableView.reloadData()
    

    @IBAction func delRowTapped(_ sender: Any) 
        numRowsTop -= 1
        // make sure it's at least 1
        numRowsTop = max(numRowsTop, 1)
        topTableView.reloadData()
    

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

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        if tableView == topTableView 
            return numRowsTop
        
        return numRowsBottom
    

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        if tableView == topTableView 
            let cell = tableView.dequeueReusableCell(withIdentifier: "SimpleTopCell", for: indexPath) as! SimpleTopCell
            cell.theLabel.text = "Top: \(indexPath)"
            return cell
        
        let cell = tableView.dequeueReusableCell(withIdentifier: "SimpleBottomCell", for: indexPath) as! SimpleBottomCell
        cell.theLabel.text = "Bottom: \(indexPath)"
        return cell
    


顶部有 8 行,底部有 12 行,我们得到:

顶部有 11 行:

最后在顶部有 17 行(滚动以便您可以看到):

这是该示例的情节提要源代码:

<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="ios.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="Qun-XE-Shi">
    <device id="retina4_7" orientation="portrait">
        <adaptation id="fullscreen"/>
    </device>
    <dependencies>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <scenes>
        <!--Auto Size Table View Controller-->
        <scene sceneID="fo7-Cf-tO5">
            <objects>
                <viewController id="Qun-XE-Shi" customClass="AutoSizeTableViewController" customModule="XC10SWScratch" customModuleProvider="target" sceneMemberID="viewController">
                    <view key="view" contentMode="scaleToFill" id="Vvb-uu-phq">
                        <rect key="frame" x="0.0" y="0.0"  />
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <subviews>
                            <stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="30" translatesAutoresizingMaskIntoConstraints="NO" id="uEB-QI-6Jy">
                                <rect key="frame" x="87.5" y="44"  />
                                <subviews>
                                    <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="qaz-hh-38L">
                                        <rect key="frame" x="0.0" y="0.0"  />
                                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                        <state key="normal" title="Add Row"/>
                                        <connections>
                                            <action selector="addRowTapped:" destination="Qun-XE-Shi" eventType="touchUpInside" id="01O-ew-Ezw"/>
                                        </connections>
                                    </button>
                                    <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="aEk-df-qAr">
                                        <rect key="frame" x="115" y="0.0"  />
                                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                        <state key="normal" title="Del Row"/>
                                        <connections>
                                            <action selector="delRowTapped:" destination="Qun-XE-Shi" eventType="touchUpInside" id="qXr-S1-utk"/>
                                        </connections>
                                    </button>
                                </subviews>
                                <constraints>
                                    <constraint firstAttribute="width" constant="200" id="zau-ia-umI"/>
                                </constraints>
                            </stackView>
                            <tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="2Kp-ZU-yGW" customClass="ContentSizedTableView" customModule="XC10SWScratch" customModuleProvider="target">
                                <rect key="frame" x="40" y="100"  />
                                <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                <constraints>
                                    <constraint firstAttribute="height" constant="240" placeholder="YES" id="BHc-OJ-3pa"/>
                                </constraints>
                                <prototypes>
                                    <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="SimpleTopCell" id="TcM-H4-6wf" customClass="SimpleTopCell" customModule="XC10SWScratch" customModuleProvider="target">
                                        <rect key="frame" x="0.0" y="28"  />
                                        <autoresizingMask key="autoresizingMask"/>
                                        <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="TcM-H4-6wf" id="Zvz-a3-fip">
                                            <rect key="frame" x="0.0" y="0.0"  />
                                            <autoresizingMask key="autoresizingMask"/>
                                            <subviews>
                                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="VZP-Nh-tor">
                                                    <rect key="frame" x="15" y="11"  />
                                                    <fontDescription key="fontDescription" type="system" pointSize="17"/>
                                                    <nil key="textColor"/>
                                                    <nil key="highlightedColor"/>
                                                </label>
                                            </subviews>
                                            <constraints>
                                                <constraint firstItem="VZP-Nh-tor" firstAttribute="top" secondItem="Zvz-a3-fip" secondAttribute="topMargin" id="0CD-yt-vZ5"/>
                                                <constraint firstItem="VZP-Nh-tor" firstAttribute="leading" secondItem="Zvz-a3-fip" secondAttribute="leadingMargin" id="7LB-3U-q99"/>
                                                <constraint firstAttribute="trailingMargin" secondItem="VZP-Nh-tor" secondAttribute="trailing" id="Pp4-PA-tvk"/>
                                                <constraint firstItem="VZP-Nh-tor" firstAttribute="bottom" secondItem="Zvz-a3-fip" secondAttribute="bottomMargin" id="xP2-ad-aPi"/>
                                            </constraints>
                                        </tableViewCellContentView>
                                        <connections>
                                            <outlet property="theLabel" destination="VZP-Nh-tor" id="aiq-L8-DYT"/>
                                        </connections>
                                    </tableViewCell>
                                </prototypes>
                            </tableView>
                            <tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="UCl-gz-0HT">
                                <rect key="frame" x="40" y="360"  />
                                <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                <prototypes>
                                    <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="SimpleBottomCell" id="PtI-n4-c5u" customClass="SimpleBottomCell" customModule="XC10SWScratch" customModuleProvider="target">
                                        <rect key="frame" x="0.0" y="28"  />
                                        <autoresizingMask key="autoresizingMask"/>
                                        <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="PtI-n4-c5u" id="bCo-w1-VQ7">
                                            <rect key="frame" x="0.0" y="0.0"  />
                                            <autoresizingMask key="autoresizingMask"/>
                                            <subviews>
                                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Inu-NF-CgL">
                                                    <rect key="frame" x="15" y="11"  />
                                                    <fontDescription key="fontDescription" type="system" pointSize="17"/>
                                                    <nil key="textColor"/>
                                                    <nil key="highlightedColor"/>
                                                </label>
                                            </subviews>
                                            <constraints>
                                                <constraint firstItem="Inu-NF-CgL" firstAttribute="bottom" secondItem="bCo-w1-VQ7" secondAttribute="bottomMargin" id="2Nz-Y2-ceX"/>
                                                <constraint firstItem="Inu-NF-CgL" firstAttribute="leading" secondItem="bCo-w1-VQ7" secondAttribute="leadingMargin" id="HIx-hC-b4c"/>
                                                <constraint firstItem="Inu-NF-CgL" firstAttribute="top" secondItem="bCo-w1-VQ7" secondAttribute="topMargin" id="Xfn-2l-Dyw"/>
                                                <constraint firstAttribute="trailingMargin" secondItem="Inu-NF-CgL" secondAttribute="trailing" id="f8F-YZ-jJh"/>
                                            </constraints>
                                        </tableViewCellContentView>
                                        <connections>
                                            <outlet property="theLabel" destination="Inu-NF-CgL" id="fsi-1C-DCU"/>
                                        </connections>
                                    </tableViewCell>
                                </prototypes>
                            </tableView>
                        </subviews>
                        <color key="backgroundColor" red="1" green="0.83234566450000003" blue="0.47320586440000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                        <constraints>
                            <constraint firstItem="UCl-gz-0HT" firstAttribute="top" secondItem="2Kp-ZU-yGW" secondAttribute="bottom" constant="20" id="2Kx-3i-Hd9"/>
                            <constraint firstItem="PTh-mY-2F7" firstAttribute="bottom" secondItem="UCl-gz-0HT" secondAttribute="bottom" constant="20" id="D50-Uk-fN0"/>
                            <constraint firstItem="PTh-mY-2F7" firstAttribute="trailing" secondItem="2Kp-ZU-yGW" secondAttribute="trailing" constant="40" id="F1H-8j-bVy"/>
                            <constraint firstItem="PTh-mY-2F7" firstAttribute="trailing" secondItem="UCl-gz-0HT" secondAttribute="trailing" constant="40" id="KXW-yh-GAA"/>
                            <constraint firstItem="uEB-QI-6Jy" firstAttribute="top" secondItem="PTh-mY-2F7" secondAttribute="top" constant="24" id="M5V-JO-Jfw"/>
                            <constraint firstItem="uEB-QI-6Jy" firstAttribute="centerX" secondItem="Vvb-uu-phq" secondAttribute="centerX" id="TlF-gf-jKf"/>
                            <constraint firstItem="2Kp-ZU-yGW" firstAttribute="top" secondItem="PTh-mY-2F7" secondAttribute="top" constant="80" id="XFo-ry-u9Y"/>
                            <constraint firstItem="2Kp-ZU-yGW" firstAttribute="leading" secondItem="PTh-mY-2F7" secondAttribute="leading" constant="40" id="iu7-sU-Gki"/>
                            <constraint firstItem="UCl-gz-0HT" firstAttribute="leading" secondItem="PTh-mY-2F7" secondAttribute="leading" constant="40" id="ni9-df-1kD"/>
                        </constraints>
                        <viewLayoutGuide key="safeArea" id="PTh-mY-2F7"/>
                    </view>
                    <navigationItem key="navigationItem" id="6mN-ug-bQV"/>
                    <connections>
                        <outlet property="bottomTableView" destination="UCl-gz-0HT" id="Yny-Gc-zhG"/>
                        <outlet property="topTableView" destination="2Kp-ZU-yGW" id="puB-6Z-xMa"/>
                    </connections>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="kps-Ns-Nci" userLabel="First Responder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="1088.8" y="2196.2518740629689"/>
        </scene>
    </scenes>
</document>

【讨论】:

爱你!非常感谢您的帮助!

以上是关于如何在 Swift 中使用两个 TableView 设计动态布局的主要内容,如果未能解决你的问题,请参考以下文章

使用swift3在tableview中搜索栏和部分

Swift 2:使用两个 CoreData 实体填充 TableView

如何使用 Swift 4 解决 Tableview 数据数组“超出范围值”?

如何将json对象的值设置为swift 3中tableView中动态呈现的视图中的标签?

如何在 Swift 中使用 MagicalRecord CoreData 删除 tableview 中的记录

如何在tableView swift的Xib Cell中创建内部视图动态