动态创建UI个元素时如何设置scrollview高度
How to set the scrollview height when UI elements are dynamically created
在故事板上,在视图控制器内我有一个滚动视图。导航栏和堆栈视图嵌入在滚动视图中。
我以编程方式在堆栈视图中逐个添加一些 UI 元素。
通过情节提要,滚动视图的约束设置为与安全区域相同 - 顶部、底部、前导、尾随和宽度。
导航栏约束 - 尾部、前导、顶部、宽度与超级视图相同。
Stackview 约束 - 尾随、前导、底部、宽度与超级视图相同。
导航栏的底部与 stackview 的顶部相同,因此它们是一个在另一个下面。
设置这些约束后,滚动视图出现错误 - 需要约束:Y 位置或高度
由于 UI 元素是动态添加到 stackview 中的,我该如何在情节提要中设置高度?有更好的方法吗?
我尝试了 "add missing constraint" 选项,它为堆栈视图添加了一个恒定的高度,但它不适用于所有设备。
感谢任何帮助,因为我是 iOS 应用程序开发的新手。谢谢
根据您的问题,您需要包含动态内容的滚动视图。您可以通过两种方式解决您的问题。首先是使用 Tableview 而不是滚动视图。但我会尝试通过您的实施来回答您的问题。
将 ScrollView 添加到 ViewController 并使用其超级视图约束顶部、底部、前导、尾随。
添加带前导、尾随、顶部和底部约束的 StackView。
每当您以编程方式添加 StackView 内容时,调用 self.view.layoutIfNeeded()
和 self.view.layoutSubviews()
。
最后设置滚动视图的内容大小scrollView.contentSize = CGSize(width:CGFloat, height: CGFloat)
一个空的UIStackView
没有固有高度,所以IB/Storyboard不知道如何满足滚动视图的contentSize
。
你需要在设计时给它一个高度限制——它可以是任何值,因为它会在运行时改变。所以,给你的堆栈视图一个高度约束,比如 300
.
当然,当您动态添加排列的子视图时,这将不允许它 "grow",因此您有几个选择。
1 - 将高度约束设置为低优先级:
这将满足 IB,但将允许堆栈视图增长。
2 - 将高度约束设置为 "placeholder":
在构建时,此约束将被删除,再次允许堆栈视图增长。
编辑: 使用第一个选项(低优先级),这就是您的文档大纲的外观:
简单示例...此class 将添加 30 个标签作为最初为空的堆栈视图的排列子视图:
import UIKit
class StackInScrollViewController: UIViewController {
@IBOutlet var theStackView: UIStackView!
override func viewDidLoad() {
super.viewDidLoad()
for i in 1...30 {
let v = UILabel()
v.translatesAutoresizingMaskIntoConstraints = false
v.backgroundColor = .yellow
v.text = "This is Label \(i)"
theStackView.addArrangedSubview(v)
}
}
}
这是情节提要来源:
<?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="v4n-Ck-gNo">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<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>
<!--Stack In Scroll View Controller-->
<scene sceneID="85i-FA-G1W">
<objects>
<viewController storyboardIdentifier="pageOne" id="v4n-Ck-gNo" customClass="StackInScrollViewController" customModule="XC10SWScratch" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="meJ-hR-GiR">
<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="h2O-la-OOI">
<rect key="frame" x="0.0" y="20" width="375" height="647"/>
<subviews>
<navigationBar contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Ozf-iG-Ogw">
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
<items>
<navigationItem title="Title" id="gMo-gQ-HLZ"/>
</items>
</navigationBar>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="FOm-go-etU">
<rect key="frame" x="0.0" y="44" width="375" height="300"/>
<constraints>
<constraint firstAttribute="height" priority="250" constant="300" id="4A2-93-8hK"/>
</constraints>
</stackView>
</subviews>
<color key="backgroundColor" red="0.46202266219999999" green="0.83828371759999998" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="FOm-go-etU" secondAttribute="trailing" id="2wm-HM-UgW"/>
<constraint firstItem="Ozf-iG-Ogw" firstAttribute="width" secondItem="h2O-la-OOI" secondAttribute="width" id="5m2-MQ-vcg"/>
<constraint firstItem="Ozf-iG-Ogw" firstAttribute="top" secondItem="h2O-la-OOI" secondAttribute="top" id="76R-nE-Vve"/>
<constraint firstAttribute="bottom" secondItem="FOm-go-etU" secondAttribute="bottom" id="ASq-4m-5zD"/>
<constraint firstAttribute="trailing" secondItem="Ozf-iG-Ogw" secondAttribute="trailing" id="GHy-BT-HmJ"/>
<constraint firstItem="FOm-go-etU" firstAttribute="width" secondItem="h2O-la-OOI" secondAttribute="width" id="LcJ-rd-yDs"/>
<constraint firstItem="Ozf-iG-Ogw" firstAttribute="leading" secondItem="h2O-la-OOI" secondAttribute="leading" id="VCw-iY-MfZ"/>
<constraint firstItem="FOm-go-etU" firstAttribute="top" secondItem="Ozf-iG-Ogw" secondAttribute="bottom" id="l3k-Nm-hTu"/>
<constraint firstItem="FOm-go-etU" firstAttribute="leading" secondItem="h2O-la-OOI" secondAttribute="leading" id="r3A-iy-6bu"/>
</constraints>
</scrollView>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="h2O-la-OOI" firstAttribute="leading" secondItem="k8i-v0-f9m" secondAttribute="leading" id="0YL-7I-Lst"/>
<constraint firstItem="h2O-la-OOI" firstAttribute="top" secondItem="k8i-v0-f9m" secondAttribute="top" id="4Zo-wX-Rir"/>
<constraint firstItem="k8i-v0-f9m" firstAttribute="bottom" secondItem="h2O-la-OOI" secondAttribute="bottom" id="FUr-4Z-b6w"/>
<constraint firstItem="k8i-v0-f9m" firstAttribute="trailing" secondItem="h2O-la-OOI" secondAttribute="trailing" id="Ic8-zA-xpZ"/>
</constraints>
<viewLayoutGuide key="safeArea" id="k8i-v0-f9m"/>
</view>
<connections>
<outlet property="theStackView" destination="FOm-go-etU" id="72X-V9-Lzg"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Ora-A0-Q75" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-327" y="165"/>
</scene>
</scenes>
</document>
在故事板上,在视图控制器内我有一个滚动视图。导航栏和堆栈视图嵌入在滚动视图中。 我以编程方式在堆栈视图中逐个添加一些 UI 元素。
通过情节提要,滚动视图的约束设置为与安全区域相同 - 顶部、底部、前导、尾随和宽度。
导航栏约束 - 尾部、前导、顶部、宽度与超级视图相同。
Stackview 约束 - 尾随、前导、底部、宽度与超级视图相同。
导航栏的底部与 stackview 的顶部相同,因此它们是一个在另一个下面。
设置这些约束后,滚动视图出现错误 - 需要约束:Y 位置或高度
由于 UI 元素是动态添加到 stackview 中的,我该如何在情节提要中设置高度?有更好的方法吗?
我尝试了 "add missing constraint" 选项,它为堆栈视图添加了一个恒定的高度,但它不适用于所有设备。 感谢任何帮助,因为我是 iOS 应用程序开发的新手。谢谢
根据您的问题,您需要包含动态内容的滚动视图。您可以通过两种方式解决您的问题。首先是使用 Tableview 而不是滚动视图。但我会尝试通过您的实施来回答您的问题。
将 ScrollView 添加到 ViewController 并使用其超级视图约束顶部、底部、前导、尾随。
添加带前导、尾随、顶部和底部约束的 StackView。
每当您以编程方式添加 StackView 内容时,调用
self.view.layoutIfNeeded()
和self.view.layoutSubviews()
。最后设置滚动视图的内容大小
scrollView.contentSize = CGSize(width:CGFloat, height: CGFloat)
一个空的UIStackView
没有固有高度,所以IB/Storyboard不知道如何满足滚动视图的contentSize
。
你需要在设计时给它一个高度限制——它可以是任何值,因为它会在运行时改变。所以,给你的堆栈视图一个高度约束,比如 300
.
当然,当您动态添加排列的子视图时,这将不允许它 "grow",因此您有几个选择。
1 - 将高度约束设置为低优先级:
这将满足 IB,但将允许堆栈视图增长。
2 - 将高度约束设置为 "placeholder":
在构建时,此约束将被删除,再次允许堆栈视图增长。
编辑: 使用第一个选项(低优先级),这就是您的文档大纲的外观:
简单示例...此class 将添加 30 个标签作为最初为空的堆栈视图的排列子视图:
import UIKit
class StackInScrollViewController: UIViewController {
@IBOutlet var theStackView: UIStackView!
override func viewDidLoad() {
super.viewDidLoad()
for i in 1...30 {
let v = UILabel()
v.translatesAutoresizingMaskIntoConstraints = false
v.backgroundColor = .yellow
v.text = "This is Label \(i)"
theStackView.addArrangedSubview(v)
}
}
}
这是情节提要来源:
<?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="v4n-Ck-gNo">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<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>
<!--Stack In Scroll View Controller-->
<scene sceneID="85i-FA-G1W">
<objects>
<viewController storyboardIdentifier="pageOne" id="v4n-Ck-gNo" customClass="StackInScrollViewController" customModule="XC10SWScratch" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="meJ-hR-GiR">
<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="h2O-la-OOI">
<rect key="frame" x="0.0" y="20" width="375" height="647"/>
<subviews>
<navigationBar contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Ozf-iG-Ogw">
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
<items>
<navigationItem title="Title" id="gMo-gQ-HLZ"/>
</items>
</navigationBar>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="FOm-go-etU">
<rect key="frame" x="0.0" y="44" width="375" height="300"/>
<constraints>
<constraint firstAttribute="height" priority="250" constant="300" id="4A2-93-8hK"/>
</constraints>
</stackView>
</subviews>
<color key="backgroundColor" red="0.46202266219999999" green="0.83828371759999998" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="FOm-go-etU" secondAttribute="trailing" id="2wm-HM-UgW"/>
<constraint firstItem="Ozf-iG-Ogw" firstAttribute="width" secondItem="h2O-la-OOI" secondAttribute="width" id="5m2-MQ-vcg"/>
<constraint firstItem="Ozf-iG-Ogw" firstAttribute="top" secondItem="h2O-la-OOI" secondAttribute="top" id="76R-nE-Vve"/>
<constraint firstAttribute="bottom" secondItem="FOm-go-etU" secondAttribute="bottom" id="ASq-4m-5zD"/>
<constraint firstAttribute="trailing" secondItem="Ozf-iG-Ogw" secondAttribute="trailing" id="GHy-BT-HmJ"/>
<constraint firstItem="FOm-go-etU" firstAttribute="width" secondItem="h2O-la-OOI" secondAttribute="width" id="LcJ-rd-yDs"/>
<constraint firstItem="Ozf-iG-Ogw" firstAttribute="leading" secondItem="h2O-la-OOI" secondAttribute="leading" id="VCw-iY-MfZ"/>
<constraint firstItem="FOm-go-etU" firstAttribute="top" secondItem="Ozf-iG-Ogw" secondAttribute="bottom" id="l3k-Nm-hTu"/>
<constraint firstItem="FOm-go-etU" firstAttribute="leading" secondItem="h2O-la-OOI" secondAttribute="leading" id="r3A-iy-6bu"/>
</constraints>
</scrollView>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="h2O-la-OOI" firstAttribute="leading" secondItem="k8i-v0-f9m" secondAttribute="leading" id="0YL-7I-Lst"/>
<constraint firstItem="h2O-la-OOI" firstAttribute="top" secondItem="k8i-v0-f9m" secondAttribute="top" id="4Zo-wX-Rir"/>
<constraint firstItem="k8i-v0-f9m" firstAttribute="bottom" secondItem="h2O-la-OOI" secondAttribute="bottom" id="FUr-4Z-b6w"/>
<constraint firstItem="k8i-v0-f9m" firstAttribute="trailing" secondItem="h2O-la-OOI" secondAttribute="trailing" id="Ic8-zA-xpZ"/>
</constraints>
<viewLayoutGuide key="safeArea" id="k8i-v0-f9m"/>
</view>
<connections>
<outlet property="theStackView" destination="FOm-go-etU" id="72X-V9-Lzg"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Ora-A0-Q75" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-327" y="165"/>
</scene>
</scenes>
</document>