swift 当UIView的动态标签足够小时,在滚动视图中垂直居中,但如果不够小,则将其对齐到顶部

ecfsfe2w  于 2023-09-29  发布在  Swift
关注(0)|答案(4)|浏览(86)

我有一个视图,里面有3个动态标签,我试图找到一种方法在滚动视图中垂直居中,但当它的动态标签太大而无法放在页面上时,请从顶部开始文本。Xcode目前正在做的是:

我想做的是:

有什么想法如何实现这一点?谢谢.

cfh9epnr

cfh9epnr1#

您可以通过将标签嵌入到堆栈视图中并将堆栈视图嵌入到UIView中来完成此操作。标签文本将垂直展开堆栈视图,堆栈视图将垂直展开内容视图,内容视图将控制滚动视图的.contentSize

黑色为滚动视图;蓝色是内容视图;堆栈视图仅显示为细灰色轮廓;标签为黄色、绿色和青色。背景颜色只是让它更容易看到什么是什么。
步骤很多,但要明确:

  • 添加一个scrollView,设置约束为正常
  • 将UIView添加到scrollView -将其命名为“contentView”
  • 为contentView的top/leading/trailing/bottom设置0约束以滚动视图
  • 将contentView的width和height设置为scrollView的width和height
  • 将stackView添加到contentView
  • 将stackView设置为Vertical / Fill / Fill / Spacing: 20
  • set stackView constraints top:8,底部:8,领先:40、尾随:40 to contentView
  • 将stackView centerY约束设置为contentView
  • 添加三个标签到stackView
  • 设置字体和文本,为中心和底部标签设置行数= 0
  • 将stackView顶部和底部约束更改为>= 8
  • 将contentView height constraint更改为Priority:250
  • 我想就这些了。

将contentView的高度Priority设置为250将允许它根据标签中的文本垂直扩展。
将top和bottom stackView约束设置为>= 8将“推动”contentView的顶部和底部,但当您没有足够的文本超出垂直边界时,允许额外的空间。
结果如下:

这里有一个故事板,所有的东西都可以参考:

<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14109" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="SeU-GX-TTY">
    <device id="retina4_7" orientation="portrait">
        <adaptation id="fullscreen"/>
    </device>
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14088"/>
        <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="bCz-Kd-LLi">
            <objects>
                <viewController id="SeU-GX-TTY" sceneMemberID="viewController">
                    <view key="view" contentMode="scaleToFill" id="qjW-fW-J5n">
                        <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="Zj2-9M-SP5" userLabel="scrollView">
                                <rect key="frame" x="0.0" y="40" width="375" height="627"/>
                                <subviews>
                                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Pmb-IH-ckB" userLabel="contentView">
                                        <rect key="frame" x="0.0" y="0.0" width="375" height="627"/>
                                        <subviews>
                                            <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="20" translatesAutoresizingMaskIntoConstraints="NO" id="EfQ-93-hcI" userLabel="stackView">
                                                <rect key="frame" x="40" y="164" width="295" height="299.5"/>
                                                <subviews>
                                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="751" text="Anger" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Sxz-f7-zjR" userLabel="topLabel">
                                                        <rect key="frame" x="0.0" y="0.0" width="295" height="43"/>
                                                        <color key="backgroundColor" red="0.99953407049999998" green="0.98835557699999999" blue="0.47265523669999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                                        <fontDescription key="fontDescription" type="system" pointSize="36"/>
                                                        <nil key="textColor"/>
                                                        <nil key="highlightedColor"/>
                                                    </label>
                                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="STy-4u-e1W" userLabel="centerLabel">
                                                        <rect key="frame" x="0.0" y="63" width="295" height="183"/>
                                                        <color key="backgroundColor" red="0.83216959239999999" green="0.98548370600000001" blue="0.47333085539999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                                        <string key="text">Anger is an intense emotion defined as a response to a perceived provocation, the invasion of one's boundaries, or a threat. From an evolutionary standpoint, anger servers to mobilise psychological resources in order to address the threat/invasion. Anger is directed at an individual of equal status.</string>
                                                        <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" verticalCompressionResistancePriority="749" text="Based on information from Wikipedia. APA DIctionary of Psycology" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="u3i-zP-e1M" userLabel="bottomLabel">
                                                        <rect key="frame" x="0.0" y="266" width="295" height="33.5"/>
                                                        <color key="backgroundColor" red="0.45138680930000002" green="0.99309605359999997" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                                        <fontDescription key="fontDescription" type="system" pointSize="14"/>
                                                        <nil key="textColor"/>
                                                        <nil key="highlightedColor"/>
                                                    </label>
                                                </subviews>
                                            </stackView>
                                        </subviews>
                                        <color key="backgroundColor" red="0.46202266219999999" green="0.83828371759999998" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                        <constraints>
                                            <constraint firstAttribute="trailing" secondItem="EfQ-93-hcI" secondAttribute="trailing" constant="40" id="4HE-oJ-RE3"/>
                                            <constraint firstItem="EfQ-93-hcI" firstAttribute="centerY" secondItem="Pmb-IH-ckB" secondAttribute="centerY" id="H9O-jj-a7A"/>
                                            <constraint firstItem="EfQ-93-hcI" firstAttribute="top" relation="greaterThanOrEqual" secondItem="Pmb-IH-ckB" secondAttribute="top" constant="8" id="cKe-DN-Lbn"/>
                                            <constraint firstItem="EfQ-93-hcI" firstAttribute="leading" secondItem="Pmb-IH-ckB" secondAttribute="leading" constant="40" id="f4g-6a-VqH"/>
                                            <constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="EfQ-93-hcI" secondAttribute="bottom" constant="8" id="meR-gT-OVG"/>
                                        </constraints>
                                    </view>
                                </subviews>
                                <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                <constraints>
                                    <constraint firstItem="Pmb-IH-ckB" firstAttribute="top" secondItem="Zj2-9M-SP5" secondAttribute="top" id="HCI-bq-7ur"/>
                                    <constraint firstAttribute="trailing" secondItem="Pmb-IH-ckB" secondAttribute="trailing" id="Tdl-c0-GAV"/>
                                    <constraint firstItem="Pmb-IH-ckB" firstAttribute="width" secondItem="Zj2-9M-SP5" secondAttribute="width" id="Zj9-ND-Fqt"/>
                                    <constraint firstItem="Pmb-IH-ckB" firstAttribute="leading" secondItem="Zj2-9M-SP5" secondAttribute="leading" id="ckv-wi-E1z"/>
                                    <constraint firstItem="Pmb-IH-ckB" firstAttribute="height" secondItem="Zj2-9M-SP5" secondAttribute="height" priority="250" id="jpK-HZ-vva"/>
                                    <constraint firstAttribute="bottom" secondItem="Pmb-IH-ckB" secondAttribute="bottom" id="psz-UW-bNp"/>
                                </constraints>
                            </scrollView>
                        </subviews>
                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                        <constraints>
                            <constraint firstItem="Zj2-9M-SP5" firstAttribute="top" secondItem="Xr7-LW-bbC" secondAttribute="top" constant="20" id="EgA-Bk-3fC"/>
                            <constraint firstItem="Zj2-9M-SP5" firstAttribute="leading" secondItem="qjW-fW-J5n" secondAttribute="leading" id="MBG-pL-R8Q"/>
                            <constraint firstItem="Xr7-LW-bbC" firstAttribute="bottom" secondItem="Zj2-9M-SP5" secondAttribute="bottom" id="e9K-6A-Y9F"/>
                            <constraint firstItem="Xr7-LW-bbC" firstAttribute="trailing" secondItem="Zj2-9M-SP5" secondAttribute="trailing" id="yfs-wt-Br8"/>
                        </constraints>
                        <viewLayoutGuide key="safeArea" id="Xr7-LW-bbC"/>
                    </view>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="lHx-xL-Vx5" userLabel="First Responder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="225" y="106"/>
        </scene>
    </scenes>
</document>

这里有一个快速的例子,只通过代码复制布局/功能:

//
//  ScrollWorkViewController.swift
//
//  Created by DonMag on 6/12/19.
//

import UIKit

class ScrollWorkViewController: UIViewController {

    let theScrollView: UIScrollView = {
        let v = UIScrollView()
        v.backgroundColor = .red
        return v
    }()
    
    let contentView: UIView = {
        let v = UIView()
        v.backgroundColor = UIColor(red: 0.25, green: 0.25, blue: 1.0, alpha: 1.0)
        return v
    }()

    let stackView: UIStackView = {
        let v = UIStackView()
        v.axis = .vertical
        v.alignment = .fill
        v.distribution = .fill
        v.spacing = 20
        return v
    }()

    let topLabel: UILabel = {
        let v = UILabel()
        v.font = UIFont.boldSystemFont(ofSize: 32.0)
        v.backgroundColor = .yellow
        return v
    }()
    
    let centerLabel: UILabel = {
        let v = UILabel()
        v.font = UIFont.systemFont(ofSize: 17.0)
        v.numberOfLines = 0
        v.backgroundColor = .green
        return v
    }()
    
    let bottomLabel: UILabel = {
        let v = UILabel()
        v.font = UIFont.systemFont(ofSize: 14.0)
        v.numberOfLines = 0
        v.backgroundColor = .cyan
        return v
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()

        [theScrollView, contentView, stackView, topLabel, centerLabel, bottomLabel].forEach {
            $0.translatesAutoresizingMaskIntoConstraints = false
        }
        
        view.addSubview(theScrollView)
        theScrollView.addSubview(contentView)
        contentView.addSubview(stackView)
        stackView.addArrangedSubview(topLabel)
        stackView.addArrangedSubview(centerLabel)
        stackView.addArrangedSubview(bottomLabel)

        let contentViewHeightConstraint = contentView.heightAnchor.constraint(equalTo: theScrollView.heightAnchor, constant: 0.0)
        contentViewHeightConstraint.priority = .defaultLow
        
        NSLayoutConstraint.activate([
            
            // constrain all 4 sides of the scroll view to the safe area
            theScrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 0.0),
            theScrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: 0.0),
            theScrollView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 0.0),
            theScrollView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: 0.0),
            
            // constrain all 4 sides of the content view to the scroll view
            contentView.topAnchor.constraint(equalTo: theScrollView.topAnchor, constant: 0.0),
            contentView.bottomAnchor.constraint(equalTo: theScrollView.bottomAnchor, constant: 0.0),
            contentView.leadingAnchor.constraint(equalTo: theScrollView.leadingAnchor, constant: 0.0),
            contentView.trailingAnchor.constraint(equalTo: theScrollView.trailingAnchor, constant: 0.0),

            // constrain width of content view to width of scroll view
            contentView.widthAnchor.constraint(equalTo: theScrollView.widthAnchor, constant: 0.0),
            
            // constrain the stack view >= 8-pts from the top
            // <= minus 8-pts from the bottom
            // 40-pts leading and trailing
            stackView.topAnchor.constraint(greaterThanOrEqualTo: contentView.topAnchor, constant: 8.0),
            stackView.bottomAnchor.constraint(lessThanOrEqualTo: contentView.bottomAnchor, constant: -8.0),
            stackView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 40.0),
            stackView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -40.0),

            // constrain stack view centerY to contentView centerY
            stackView.centerYAnchor.constraint(equalTo: contentView.centerYAnchor, constant: 0.0),
            
            // activate the contentView's height constraint
            contentViewHeightConstraint,
            
            ])
        
        topLabel.text = "Anger"
        bottomLabel.text = "Based on information from Wikipedia APA Dictionary of Psychology"

        // a sample paragraph of text
        let centerSampleText = "Anger is an intense emotion defined as a response to a perceived provocation, the invasion of one’s boundaries, or a threat. From an evolutionary standpoint, anger servers to mobilise psychological resources in order to address the threat/invasion. Anger is directed at an individual of equal status."

        // change to repeat the center-label sample text
        let numberOfParagraphs = 2
        
        var s = ""
        
        for i in 1...numberOfParagraphs {
            s += "\(i). " + centerSampleText
            if i < numberOfParagraphs {
                s += "\n\n"
            }
        }
        
        centerLabel.text = s
        
    }
    
}

编辑-由于这个答案仍然偶尔会得到“支持票”,我已经更新了代码,以反映滚动视图.contentLayoutGuide.frameFlayoutGuide的更现代的用法。还添加了按钮,以交互方式添加/删除文本演示居中。

class ScrollWorkViewController: UIViewController {
    
    let theScrollView: UIScrollView = {
        let v = UIScrollView()
        v.backgroundColor = .systemYellow
        return v
    }()
    
    let contentView: UIView = {
        let v = UIView()
        v.backgroundColor = .systemBlue
        return v
    }()
    
    let stackView: UIStackView = {
        let v = UIStackView()
        v.axis = .vertical
        v.alignment = .fill
        v.distribution = .fill
        v.spacing = 20
        return v
    }()
    
    let topLabel: UILabel = {
        let v = UILabel()
        v.font = UIFont.boldSystemFont(ofSize: 32.0)
        v.backgroundColor = .yellow
        return v
    }()
    
    let centerLabel: UILabel = {
        let v = UILabel()
        v.font = UIFont.systemFont(ofSize: 17.0)
        v.numberOfLines = 0
        v.backgroundColor = .green
        return v
    }()
    
    let bottomLabel: UILabel = {
        let v = UILabel()
        v.font = UIFont.systemFont(ofSize: 14.0)
        v.numberOfLines = 0
        v.backgroundColor = .cyan
        return v
    }()
    
    // a sample paragraph of text
    let centerSampleText = "Anger is an intense emotion defined as a response to a perceived provocation, the invasion of one’s boundaries, or a threat. From an evolutionary standpoint, anger servers to mobilise psychological resources in order to address the threat/invasion. Anger is directed at an individual of equal status."
    
    // update the center-label text when numberOfParagraphs changes
    var numberOfParagraphs = 1 {
        didSet {
            var s = ""
            for i in 1...numberOfParagraphs {
                s += "\(i). " + centerSampleText
                if i < numberOfParagraphs {
                    s += "\n\n"
                }
            }
            centerLabel.text = s
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let btnA = UIButton()
        btnA.setTitle("Add", for: [])
        btnA.setTitleColor(.white, for: .normal)
        btnA.setTitleColor(.lightGray, for: .highlighted)
        btnA.backgroundColor = .systemGreen

        let btnB = UIButton()
        btnB.setTitle("Remove", for: [])
        btnB.setTitleColor(.white, for: .normal)
        btnB.setTitleColor(.lightGray, for: .highlighted)
        btnB.backgroundColor = .systemRed

        [btnA, btnB, theScrollView, contentView, stackView, topLabel, centerLabel, bottomLabel].forEach {
            $0.translatesAutoresizingMaskIntoConstraints = false
        }
        
        view.addSubview(btnA)
        view.addSubview(btnB)
        view.addSubview(theScrollView)
        theScrollView.addSubview(contentView)
        contentView.addSubview(stackView)
        stackView.addArrangedSubview(topLabel)
        stackView.addArrangedSubview(centerLabel)
        stackView.addArrangedSubview(bottomLabel)
        
        let g = view.safeAreaLayoutGuide
        let cg = theScrollView.contentLayoutGuide
        let fg = theScrollView.frameLayoutGuide
        
        // constrain height of content view to height of scroll view's Frame Layout Guide
        //  with less-than-required Priority so it can get taller when the content gets taller
        let contentViewHeightConstraint = contentView.heightAnchor.constraint(equalTo: fg.heightAnchor, constant: 0.0)
        contentViewHeightConstraint.priority = .defaultLow
        
        NSLayoutConstraint.activate([
            
            // constrain buttons at top
            btnA.topAnchor.constraint(equalTo: g.topAnchor, constant: 8.0),
            btnA.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),

            btnB.topAnchor.constraint(equalTo: g.topAnchor, constant: 8.0),
            btnB.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
            
            btnB.leadingAnchor.constraint(equalTo: btnA.trailingAnchor, constant: 20.0),
            btnB.widthAnchor.constraint(equalTo: btnA.widthAnchor),

            // constrain scroll view Top to buttons Bottom plus 8-points "spacing"
            //  leading/trailing/bottom to the safe area
            theScrollView.topAnchor.constraint(equalTo: btnA.bottomAnchor, constant: 8.0),
            theScrollView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 0.0),
            theScrollView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: 0.0),
            theScrollView.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: 0.0),

            // constrain all 4 sides of the content view to the scroll view's Content Layout Guide
            contentView.topAnchor.constraint(equalTo: cg.topAnchor, constant: 0.0),
            contentView.leadingAnchor.constraint(equalTo: cg.leadingAnchor, constant: 0.0),
            contentView.trailingAnchor.constraint(equalTo: cg.trailingAnchor, constant: 0.0),
            contentView.bottomAnchor.constraint(equalTo: cg.bottomAnchor, constant: 0.0),

            // constrain width of content view to width of scroll view's Frame Layout Guide
            contentView.widthAnchor.constraint(equalTo: fg.widthAnchor, constant: 0.0),
            
            // constrain the stack view >= 8-pts from the top
            // <= minus 8-pts from the bottom
            // 40-pts leading and trailing
            stackView.topAnchor.constraint(greaterThanOrEqualTo: contentView.topAnchor, constant: 8.0),
            stackView.bottomAnchor.constraint(lessThanOrEqualTo: contentView.bottomAnchor, constant: -8.0),
            stackView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 40.0),
            stackView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -40.0),
            
            // constrain stack view centerY to contentView centerY
            stackView.centerYAnchor.constraint(equalTo: contentView.centerYAnchor, constant: 0.0),
            
            // activate the contentView's height constraint
            contentViewHeightConstraint,
            
        ])
        
        topLabel.text = "Anger"
        bottomLabel.text = "Based on information from Wikipedia APA Dictionary of Psychology"
        
        numberOfParagraphs = 1
        
        btnA.addTarget(self, action: #selector(addTapped(_:)), for: .touchUpInside)
        btnB.addTarget(self, action: #selector(removeTapped(_:)), for: .touchUpInside)
        
    }
    
    @objc func addTapped(_ sender: Any?) {
        numberOfParagraphs += 1
    }
    @objc func removeTapped(_ sender: Any?) {
        if numberOfParagraphs > 1 {
            numberOfParagraphs -= 1
        }
    }

}

对于一两个段落,内容不够高,无法滚动,但仍保持垂直居中:

对于3个或更多段落(在iPhone SE上),我们现在可以滚动:

wfveoks0

wfveoks02#

为了补充DonMag的答案,您实际上可以通过仅使用UIScrollViewUIStackView来完成完全相同的事情。这适用于iOS 11及更高版本,因为它使用UIScrollView上的contentLayoutGuideframeLayoutGuide属性。
当我提到滚动视图的内容视图时,它只是指滚动视图中的可滚动内容布局区域。它指的是内容布局指南,而不是堆栈视图。
步骤如下,用伪代码编写(只需添加等效的约束):

  1. scrollView.contentLayoutGuide.height >= scrollView.frameLayoutGuide.height-这将滚动视图内容设置为至少与滚动视图本身一样高。通过这样做,我们还不能完全集中内容。
  2. stackView.centerY == scrollView.contentLayoutGuide.centerY-这将强制堆栈视图与滚动视图内容视图垂直居中。但是等等,如果堆栈视图太短怎么办?请记住,在第1步中,我们强制内容大小至少与滚动视图本身一样高。这意味着,如果堆栈视图不够高,不足以引起滚动,它实际上将在内容视图中居中,内容视图与滚动视图一样高,从而引起期望的效果。
  3. stackView.top/bottom <= (inside) scrollView.contentLayoutGuide.top/bottom-这只是设置堆栈视图的边缘,以便顶部和底部位于滚动视图的内容视图内。
    1.(可选)stackView.top/bottom == (inside) scrollView.contentLayoutGuide.top/bottom with defaultLow priority -这将强制滚动视图的内容视图具有固有高度,以防视图调试器出现问题。
    这对于垂直约束应该是足够的。添加必要的水平约束,一切都应该很好!
4zcjmb1e

4zcjmb1e3#

我也遇到过同样的问题,当标签没有填满scrollView(否则顶部对齐)时,我试图在scrollView中垂直居中标签,并找到了一个简单的解决方案,因为它是脏的,所有在IB中没有扩展或子类。
首先,在处理UIScrollView时设置通常的约束:
1.限制到scrollView内容布局指南的顶部、底部、前导、尾随子视图
1.子视图宽度等于scrollView宽度
然后使子视图的高度大于或等于scrollView的高度(这会触发一个约束错误)。现在,将此约束乘数设置为接近1但不完全为1的任何值(例如:0.999999)。约束错误消失,子视图的行为符合预期。
这一点并不值得骄傲,但它可以保存一些时间,人们在匆忙。

pxiryf3j

pxiryf3j4#

巨大的 prop 给DonMag的伟大解释。然而,由于某种原因,当我实现它时,我的ScrollView不会滚动。下面是对我有用的,在Xcode 13的Interface Builder中,所以你可以看到ScrollView的Content Layout GuideFrame Layout Guide约束。

步骤:

  • Scroll View拖到视图控制器中。引脚领先/顶部/尾随/底部的Safe Area或任何。这将确定Scroll View的帧,从而确定Frame Layout Guide
  • 将虚拟常规View拖动到Scroll View中。将leading/top/trailing/bottom固定到Scroll ViewContent Layout Guide(滚动视图的“内部”)。这些约束允许这个新View的大小来确定滚动视图的可滚动区域:如果View大于滚动视图的框架,则滚动视图将允许滚动,否则不允许。现在我们只需要设置View的大小;它立场无关紧要。(如果Scroll View允许滚动,则默认情况下将从顶部开始“向上滚动”。
  • 我们的最终目标是将我们的内容集中在这个View中。因此,View的 * 最小尺寸 * 应该是总的可见区域,也就是Scroll View的框架。假设我们只想允许垂直滚动,将View的宽度设置为Scroll ViewFrame Layout Guide宽度。另外,将View的高度设置为 * 大于或等于 * Scroll ViewFrame Layout Guide高度,因为我们当然希望启用垂直滚动 * 如果 * View中的内容大于滚动视图的框架。
  • Stack View(或您想要的任何视图/内容)拖到View中。将Stack ViewcenterY设置为其superview的centerY
  • 此时,内容将显示为垂直居中,但自动布局没有足够的信息来确定View的高度。我们之前设定了一个最小高度,那么最大高度呢?这可以通过另一个约束来满足:将Stack View的高度设置为 * 小于或等于 * Views的高度。这将神奇地确保如果Stack View的高度增长超过View的最小高度,View的高度将相应地增加,使该区域可滚动。(请注意,还有其他方法可以设置View的高度,例如使用View的子视图的顶部和底部引用,如其他答案所示。)
  • 最后,根据需要设置Stack View的水平约束。

不幸的是,界面生成器抱怨“滚动视图需要约束:Y位置或高度”这可能是一个Xcode / auto布局错误?我在控制台中没有看到任何错误。

相关问题