带有容器视图的滚动视图无法正确调整内容大小

时间:2019-08-04 16:48:39

标签: swift uiscrollview uikit

我有一个这样排列的视图层次结构:

def format_based():
    rules = {
        'X': lambda: random.choice(["{F}{X}{F}{F}+", "+{X}{X}{F}{J}]"]),
        'F': lambda: 'F',
        'J': lambda: 'J',
    }
    def get_callbacks():
        while True:
            yield {k: v() for k, v in rules.items()}
    callbacks = get_callbacks()
    L_string = "{F}{X}"
    for _ in range(5):
        L_string = L_string.format(**next(callbacks))
    return re.sub('{|}', '', L_string)

嵌入式子视图控制器是 UICollectionViewController

现在的问题是,集合视图控制器包含许多元素,我希望滚动视图也能自动调整其内容大小,以便也考虑到集合视图的高度,但事实并非如此。因此,目前我只能看到集合视图的前几个元素,但无法向下滚动。我试图通过这种方式手动调整集合视图的内容大小:

main view
---- scroll view
-------- label
-------- label
-------- text view
-------- horizontal stack view
-------- divider view (UIView)
-------- label
-------- container view (embeds a child view controller)

但是内容大小仍然不正确:它等于窗口大小,即使应该更大一些,以便为集合视图中的所有元素留出空间。我认为问题主要与我嵌入子视图控制器有关,因为通常滚动视图内容的大小会自动调整。但是在这种情况下该怎么办?如何告诉滚动视图正确的内容大小?

4 个答案:

答案 0 :(得分:1)

在容器视图上设置约束与在任何其他视图上设置没有什么不同。

这是您的布局,但有限制:

enter image description here

在运行时看起来像这样:

enter image description here

然后滚动:

enter image description here

这是所有需要的代码(集合视图使用“水平流”):

//
//  ViewController.swift
//  Ramy
//
//  Created by Don Mag on 8/7/19.
//

import UIKit

class ViewController: UIViewController {

}

extension UIColor {
    static var random: UIColor {
        return UIColor(red: .random(in: 0...1),
                       green: .random(in: 0...1),
                       blue: .random(in: 0...1),
                       alpha: 1.0)
    }
}

class EmbeddedCollectionViewController: UICollectionViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "ReuseID")
    }

    override func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }

    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 100
    }

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ReuseID", for: indexPath)
        cell.backgroundColor = UIColor.random
        return cell

    }

}

以及情节提要的源代码:

<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14490.70" 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="14490.49"/>
        <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="Ramy" 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>
                            <scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="jJS-Jp-5Wb">
                                <rect key="frame" x="8" y="28" width="359" height="631"/>
                                <subviews>
                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label 1" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="XwC-bl-fns">
                                        <rect key="frame" x="153" y="8" width="53.5" height="20.5"/>
                                        <color key="backgroundColor" red="0.99806135890000003" green="0.96808904409999996" blue="0.12760734560000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                        <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="Label 2" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="VcB-Di-yle">
                                        <rect key="frame" x="151.5" y="40.5" width="56" height="20.5"/>
                                        <color key="backgroundColor" red="0.99806135890000003" green="0.96808904409999996" blue="0.12760734560000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                        <fontDescription key="fontDescription" type="system" pointSize="17"/>
                                        <nil key="textColor"/>
                                        <nil key="highlightedColor"/>
                                    </label>
                                    <textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" textAlignment="natural" translatesAutoresizingMaskIntoConstraints="NO" id="2P9-JD-ezE">
                                        <rect key="frame" x="59.5" y="73" width="240" height="128"/>
                                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                        <constraints>
                                            <constraint firstAttribute="width" constant="240" id="RSb-O4-Jy1"/>
                                            <constraint firstAttribute="height" constant="128" id="ZNr-Tq-dig"/>
                                        </constraints>
                                        <string key="text">Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda.</string>
                                        <fontDescription key="fontDescription" type="system" pointSize="14"/>
                                        <textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
                                    </textView>
                                    <stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="Urd-av-tKj">
                                        <rect key="frame" x="54" y="213" width="251.5" height="20.5"/>
                                        <subviews>
                                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Horizontal" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="iJ9-BV-XXm">
                                                <rect key="frame" x="0.0" y="0.0" width="78.5" height="20.5"/>
                                                <color key="backgroundColor" red="0.99806135890000003" green="0.96808904409999996" blue="0.12760734560000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                                <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="Stack" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="SlW-MH-lZj">
                                                <rect key="frame" x="86.5" y="0.0" width="78.5" height="20.5"/>
                                                <color key="backgroundColor" red="0.99806135890000003" green="0.96808904409999996" blue="0.12760734560000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                                <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="View" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="usj-S2-wXe">
                                                <rect key="frame" x="173" y="0.0" width="78.5" height="20.5"/>
                                                <color key="backgroundColor" red="0.99806135890000003" green="0.96808904409999996" blue="0.12760734560000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                                <fontDescription key="fontDescription" type="system" pointSize="17"/>
                                                <nil key="textColor"/>
                                                <nil key="highlightedColor"/>
                                            </label>
                                        </subviews>
                                    </stackView>
                                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Ube-Ox-WG0" userLabel="Divider View">
                                        <rect key="frame" x="29.5" y="253.5" width="300" height="4"/>
                                        <color key="backgroundColor" red="1" green="0.14913141730000001" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                        <constraints>
                                            <constraint firstAttribute="width" constant="300" id="3r0-U8-e4h"/>
                                            <constraint firstAttribute="height" constant="4" id="8Zh-29-VuE"/>
                                        </constraints>
                                    </view>
                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label 3" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="t4g-6L-Fxz">
                                        <rect key="frame" x="151.5" y="277.5" width="56.5" height="20.5"/>
                                        <color key="backgroundColor" red="0.99806135890000003" green="0.96808904409999996" blue="0.12760734560000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                        <fontDescription key="fontDescription" type="system" pointSize="17"/>
                                        <nil key="textColor"/>
                                        <nil key="highlightedColor"/>
                                    </label>
                                    <containerView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Ae9-nr-NPW">
                                        <rect key="frame" x="12" y="310" width="335" height="500"/>
                                        <color key="backgroundColor" red="0.16078431369999999" green="0.62352941179999999" blue="0.81960784310000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                        <constraints>
                                            <constraint firstAttribute="height" constant="500" id="Ugi-NN-btd"/>
                                        </constraints>
                                        <connections>
                                            <segue destination="iKt-In-mH7" kind="embed" id="xc0-HZ-ykL"/>
                                        </connections>
                                    </containerView>
                                </subviews>
                                <color key="backgroundColor" red="0.99942404029999998" green="0.88699374509999995" blue="0.6455106089" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                <constraints>
                                    <constraint firstItem="Ae9-nr-NPW" firstAttribute="leading" secondItem="jJS-Jp-5Wb" secondAttribute="leading" constant="12" id="46G-Do-tx2"/>
                                    <constraint firstItem="Ae9-nr-NPW" firstAttribute="width" secondItem="jJS-Jp-5Wb" secondAttribute="width" constant="-24" id="9Gx-Qt-KD7"/>
                                    <constraint firstItem="VcB-Di-yle" firstAttribute="centerX" secondItem="2P9-JD-ezE" secondAttribute="centerX" id="AbA-b2-Dc2"/>
                                    <constraint firstItem="Ube-Ox-WG0" firstAttribute="centerX" secondItem="t4g-6L-Fxz" secondAttribute="centerX" id="J1X-MF-qh8"/>
                                    <constraint firstAttribute="bottom" secondItem="Ae9-nr-NPW" secondAttribute="bottom" constant="8" id="J4e-Iv-CbW"/>
                                    <constraint firstItem="VcB-Di-yle" firstAttribute="top" secondItem="XwC-bl-fns" secondAttribute="bottom" constant="12" id="Lbs-Pa-kn0"/>
                                    <constraint firstItem="Urd-av-tKj" firstAttribute="top" secondItem="2P9-JD-ezE" secondAttribute="bottom" constant="12" id="MnP-kq-VMd"/>
                                    <constraint firstItem="Ube-Ox-WG0" firstAttribute="top" secondItem="Urd-av-tKj" secondAttribute="bottom" constant="20" id="Nzj-mz-NBe"/>
                                    <constraint firstItem="2P9-JD-ezE" firstAttribute="top" secondItem="VcB-Di-yle" secondAttribute="bottom" constant="12" id="PV8-rx-82P"/>
                                    <constraint firstItem="t4g-6L-Fxz" firstAttribute="centerX" secondItem="Ae9-nr-NPW" secondAttribute="centerX" id="R8B-Yu-eaX"/>
                                    <constraint firstAttribute="trailing" secondItem="Ae9-nr-NPW" secondAttribute="trailing" constant="12" id="Vl6-pC-fR7"/>
                                    <constraint firstItem="t4g-6L-Fxz" firstAttribute="top" secondItem="Ube-Ox-WG0" secondAttribute="bottom" constant="20" id="dzM-uC-vDg"/>
                                    <constraint firstItem="2P9-JD-ezE" firstAttribute="centerX" secondItem="Urd-av-tKj" secondAttribute="centerX" id="gIG-Ln-0ci"/>
                                    <constraint firstItem="XwC-bl-fns" firstAttribute="top" secondItem="jJS-Jp-5Wb" secondAttribute="top" constant="8" id="h2g-bu-iYg"/>
                                    <constraint firstItem="Ae9-nr-NPW" firstAttribute="top" secondItem="t4g-6L-Fxz" secondAttribute="bottom" constant="12" id="k5A-Ht-wuD"/>
                                    <constraint firstItem="XwC-bl-fns" firstAttribute="centerX" secondItem="VcB-Di-yle" secondAttribute="centerX" id="s7H-0G-55o"/>
                                    <constraint firstItem="Urd-av-tKj" firstAttribute="centerX" secondItem="Ube-Ox-WG0" secondAttribute="centerX" id="wIn-jA-Hwn"/>
                                </constraints>
                            </scrollView>
                        </subviews>
                        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                        <constraints>
                            <constraint firstItem="jJS-Jp-5Wb" firstAttribute="top" secondItem="6Tk-OE-BBY" secondAttribute="top" constant="8" id="HZI-i3-eQL"/>
                            <constraint firstItem="6Tk-OE-BBY" firstAttribute="trailing" secondItem="jJS-Jp-5Wb" secondAttribute="trailing" constant="8" id="TrF-oh-lbk"/>
                            <constraint firstItem="6Tk-OE-BBY" firstAttribute="bottom" secondItem="jJS-Jp-5Wb" secondAttribute="bottom" constant="8" id="gCW-Kv-Vma"/>
                            <constraint firstItem="jJS-Jp-5Wb" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" constant="8" id="mdg-vi-3RB"/>
                        </constraints>
                        <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
                    </view>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="138.40000000000001" y="138.98050974512745"/>
        </scene>
        <!--Embedded Collection View Controller-->
        <scene sceneID="8Wg-59-nK4">
            <objects>
                <collectionViewController id="iKt-In-mH7" customClass="EmbeddedCollectionViewController" customModule="Ramy" customModuleProvider="target" sceneMemberID="viewController">
                    <collectionView key="view" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="prototypes" id="pbM-fa-YQc">
                        <rect key="frame" x="0.0" y="0.0" width="335" height="500"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                        <collectionViewFlowLayout key="collectionViewLayout" scrollDirection="horizontal" minimumLineSpacing="10" minimumInteritemSpacing="10" id="Sd4-5y-JzD">
                            <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" misplaced="YES" id="UTC-Yv-lrd">
                                <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"/>
                                </view>
                            </collectionViewCell>
                        </cells>
                        <connections>
                            <outlet property="dataSource" destination="iKt-In-mH7" id="KsO-Bh-EEm"/>
                            <outlet property="delegate" destination="iKt-In-mH7" id="IOW-gi-oV8"/>
                        </connections>
                    </collectionView>
                </collectionViewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="PLD-Y7-bEq" userLabel="First Responder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="888.79999999999995" y="312.14392803598201"/>
        </scene>
    </scenes>
</document>

答案 1 :(得分:0)

我不明白为什么您不能为所有这些视图设置约束?我知道一个约束是两个视图之间的关系,但是多个约束可以为所有这些视图建立关系。

对于您的情况,在scrollview中有7个视图,您可以执行以下操作,

scrollview.top = view1.top
view2.top = view1.bottom
view3.top = view2.bottom
...
view7.bottom = scrollview.bottom
// don't forget to set this
scrollview.top = scrollviewParent.top
scrollview.bottom = scrollviewParent.bottom
scrollview.leading = scrollviewParent.leading
scrollview.trailing = scrollviewParent.trailing

因此所有这些约束都应该起作用。

答案 2 :(得分:0)

似乎对滚动视图的工作方式感到困惑。滚动视图是屏幕上的“固定”高度区域,可在其“ contentView”高度上滚动(此处是垂直滚动)。

当然,您的主滚动视图将环绕内容并自动调整高度,但请记住,UICollectionView也是UIScrollView的扩展,它将在其父视图设置的范围内滚动其contentView的高度(此处为容器查看)

我希望您现在看到问题,设置固定大小或使用自动布局确定“ ContainerView”的高度,然后主滚动视图基于此调整其“ contentView”。这也迫使您的UICollectionView只能在该高度上滚动。问题是,如果您的collectionview是动态的,则您不知道在构建时将其设置为的高度。发生的事情是,您可以滚动到主滚动视图的末尾,它将显示容器视图的推断高度或固定高度,在该高度内也应该可以滚动!! (如果愿意,可以使用嵌套的滚动视图)

解决方案似乎如下。您将需要推断您的collectionview的行数,并设置containerview的高度以与此匹配(height_per_item * no_of_rows)。然后滚动查看  会围绕这个总高度,并提供整个contentView高度的滚动(由于不使用collectionview,因此最好谨慎关闭垂直滚动,因为它将不被使用。我不完全了解嵌套滚动视图对性能的影响)

答案 3 :(得分:0)

如果问题是ScrollView ContentSize。则应基于(高度+组件的边距(标签,TextView,StatckView))加上CollectionView.contentSize.height设置内容大小

和约束应在控制器B上重新加载CollectionView之后设置

示例

ViewControllerA

let ViewControllerB = self.storyboard?.instantiateViewController(withIdentifier: "ViewControllerB") as! ViewControllerB
        ViewControllerB.compltion = { collectionHeight in
            ScrollView.heightConstaint.constant = 500 + collectionHeight
        }

这里500是顶部+底部页边距+其他组件(stackView,Label,TextView)的高度

ViewControllerB

override func viewDidLoad() {
        super.viewDidLoad()

        self.collectioView.reloadData()
        self.collectioView.performBatchUpdates(nil, completion: {
            (result) in
            if self.compltion != nil {
                self.compltion!(self.collectioView.contentSize.height)
            }
        })


        // Do any additional setup after loading the view.
    }