我有我的视图控制器和 xib 文件。在 xib 文件中,在主视图上我有一个子视图。子视图包含按钮上方的滚动视图。滚动视图的内容视图包含文本标签和文本视图。文本标签和文本视图的字符串源自字符串文件。文本视图的第二个文本可能来自多个文件之一,并且往往具有较大的文本,但情况有所不同。文本视图不可滚动。该按钮的高度是固定的。
我想要什么 - 包含滚动视图和按钮的 UIView 需要根据滚动视图的内容来增大或缩小,但是包含所有内容的 UIView 也不应该增长到大于设备屏幕的顶部和底部约束。如果可能的话,滚动视图应将其大小最小化为内容视图的大小。如果两个文本标签的大小(由于它们的字符串大小)足够大,则滚动视图应该根据其内容视图增长以匹配该大小,直到包含它和按钮的 UIView 的大小适合。一旦包含滚动视图和按钮的 UIView 达到其最大尺寸,按钮仍应固定在底部,滚动视图应占据屏幕的其余部分,此时,如果文本为还更大。
我可以通过编程来完成此操作。这不是什么大问题。我想完全通过 xib 和界面生成器来完成此操作,但我不确定如何使用那里给出的约束选项来解决这个问题。我花了大约 6 个小时尝试不同的事情,但我就是不明白。有什么帮助吗?
这是可以做到的——但是有点复杂。技巧是将滚动视图的高度限制为“内容”视图的高度......具有各种大于/小于/不同的约束优先级和内容拥抱优先级。
写出所有步骤非常困难,所以这是 XIB 的图片:
这是 XIB 视图类,以及
NibLoadable
协议和扩展:
class TinyTimXIB: UIView, NibLoadable {
@IBOutlet weak var myLabel: UILabel!
@IBOutlet weak var myTV: UITextView!
var numLines: Int = 0
var nInc: Int = 2
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupFromNib()
}
override init(frame: CGRect) {
super.init(frame: frame)
setupFromNib()
}
@IBAction func didTap(_ sender: Any) {
print("did tap")
numLines += nInc
if numLines > 15 {
nInc = -2
} else if numLines < 4 {
nInc = 2
}
let s = (2...numLines).compactMap( { "Line \($0)" } ).joined(separator: "\n")
myTV.text = "UITextView\n" + s
guard let btn = sender as? UIButton else { return }
var cfg = btn.configuration
var t: String = nInc > 0 ? "Add Lines" : "Remove Lines"
t += " - Current: \(numLines)"
cfg?.title = t
btn.configuration = cfg
}
}
public protocol NibLoadable {
static var nibName: String { get }
}
public extension NibLoadable where Self: UIView {
static var nibName: String {
return String(describing: Self.self) // defaults to the name of the class implementing this protocol.
}
static var nib: UINib {
let bundle = Bundle(for: Self.self)
return UINib(nibName: Self.nibName, bundle: bundle)
}
func setupFromNib() {
guard let view = Self.nib.instantiate(withOwner: self, options: nil).first as? UIView else { fatalError("Error loading \(self) from nib") }
addSubview(view)
view.translatesAutoresizingMaskIntoConstraints = false
view.leadingAnchor.constraint(equalTo: self.safeAreaLayoutGuide.leadingAnchor, constant: 0).isActive = true
view.topAnchor.constraint(equalTo: self.safeAreaLayoutGuide.topAnchor, constant: 0).isActive = true
view.trailingAnchor.constraint(equalTo: self.safeAreaLayoutGuide.trailingAnchor, constant: 0).isActive = true
view.bottomAnchor.constraint(equalTo: self.safeAreaLayoutGuide.bottomAnchor, constant: 0).isActive = true
}
}
将其添加为视图控制器中的子视图:
所有 4 边都有 20 点填充。
每次点击按钮都会添加几行,直到达到 16 条,然后每次点击都会删除几行。一旦我们达到 12 行(在 iPhone 15 Pro 上),滚动视图就会停止增长并变得可滚动:
这是 XIB 文件的源代码,以便您可以使用 IB 来检查它:
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="22154" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait" appearance="light"/>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22130"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="TinyTimXIB" customModule="scratch202401" customModuleProvider="target">
<connections>
<outlet property="myLabel" destination="ngF-8x-hAl" id="SfW-3V-ZsK"/>
<outlet property="myTV" destination="3e6-OZ-aFR" id="K2o-YH-3In"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="NN7-sN-S8u">
<rect key="frame" x="0.0" y="0.0" width="432" height="671"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Co8-1S-Ok1">
<rect key="frame" x="8" y="28" width="416" height="252.5"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="k07-XG-JE8" userLabel="CView">
<rect key="frame" x="20" y="20" width="376" height="212.5"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="1000" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ngF-8x-hAl" userLabel="MyLabel">
<rect key="frame" x="8" y="8" width="360" height="29"/>
<color key="backgroundColor" red="0.99953407049999998" green="0.98835557699999999" blue="0.47265523669999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<fontDescription key="fontDescription" type="system" pointSize="24"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" verticalHuggingPriority="1000" scrollEnabled="NO" editable="NO" textAlignment="natural" selectable="NO" translatesAutoresizingMaskIntoConstraints="NO" id="3e6-OZ-aFR" userLabel="MyTV">
<rect key="frame" x="8" y="45" width="360" height="159.5"/>
<color key="backgroundColor" red="0.55634254220000001" green="0.97934550050000002" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<string key="text">UITextView
Text will be dynamic...</string>
<color key="textColor" systemColor="labelColor"/>
<fontDescription key="fontDescription" type="system" pointSize="40"/>
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
</textView>
</subviews>
<color key="backgroundColor" red="0.46202266219999999" green="0.83828371759999998" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="3e6-OZ-aFR" firstAttribute="top" secondItem="ngF-8x-hAl" secondAttribute="bottom" constant="8" id="8q7-Qe-qqo"/>
<constraint firstItem="3e6-OZ-aFR" firstAttribute="top" secondItem="ngF-8x-hAl" secondAttribute="bottom" constant="8" id="9xR-by-3kr"/>
<constraint firstItem="ngF-8x-hAl" firstAttribute="leading" secondItem="k07-XG-JE8" secondAttribute="leading" constant="8" id="fHY-O5-b28"/>
<constraint firstItem="3e6-OZ-aFR" firstAttribute="leading" secondItem="k07-XG-JE8" secondAttribute="leading" constant="8" id="kmr-Sg-lga"/>
<constraint firstAttribute="bottom" secondItem="3e6-OZ-aFR" secondAttribute="bottom" constant="8" id="qSL-aL-gs3"/>
<constraint firstItem="ngF-8x-hAl" firstAttribute="top" secondItem="k07-XG-JE8" secondAttribute="top" constant="8" id="qh3-II-CX1"/>
<constraint firstAttribute="trailing" secondItem="3e6-OZ-aFR" secondAttribute="trailing" constant="8" id="qjo-yL-8ID"/>
<constraint firstAttribute="trailing" secondItem="ngF-8x-hAl" secondAttribute="trailing" constant="8" id="sDe-jO-WhS"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" red="1" green="0.79083781379999996" blue="0.99597025539999995" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="height" relation="lessThanOrEqual" secondItem="k07-XG-JE8" secondAttribute="height" constant="40" id="5LD-n0-Hd9"/>
<constraint firstItem="k07-XG-JE8" firstAttribute="height" secondItem="V8E-tM-mHa" secondAttribute="height" priority="250" constant="-40" id="CFn-Ik-QU0"/>
<constraint firstItem="k07-XG-JE8" firstAttribute="bottom" secondItem="jwi-97-yB3" secondAttribute="bottom" constant="-20" id="PWZ-Mc-QtM"/>
<constraint firstItem="k07-XG-JE8" firstAttribute="trailing" secondItem="jwi-97-yB3" secondAttribute="trailing" constant="20" id="V1S-dA-dr2"/>
<constraint firstItem="k07-XG-JE8" firstAttribute="width" secondItem="V8E-tM-mHa" secondAttribute="width" constant="-40" id="d65-Os-mzF"/>
<constraint firstItem="k07-XG-JE8" firstAttribute="top" secondItem="jwi-97-yB3" secondAttribute="top" constant="20" id="gsd-cg-ISa"/>
<constraint firstItem="k07-XG-JE8" firstAttribute="leading" secondItem="jwi-97-yB3" secondAttribute="leading" constant="20" id="o4f-sM-k2h"/>
</constraints>
<viewLayoutGuide key="contentLayoutGuide" id="jwi-97-yB3"/>
<viewLayoutGuide key="frameLayoutGuide" id="V8E-tM-mHa"/>
</scrollView>
<button opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="1000" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="0fT-vS-7VT" userLabel="AddLinesBtn">
<rect key="frame" x="8" y="613" width="416" height="50"/>
<constraints>
<constraint firstAttribute="height" constant="50" id="TU4-0f-Y8Z"/>
</constraints>
<state key="normal" title="Button"/>
<buttonConfiguration key="configuration" style="filled" title="Add Lines"/>
<connections>
<action selector="didTap:" destination="-1" eventType="touchUpInside" id="ToM-EE-Sjz"/>
</connections>
</button>
</subviews>
<viewLayoutGuide key="safeArea" id="JWK-TM-5X8"/>
<color key="backgroundColor" systemColor="systemYellowColor"/>
<constraints>
<constraint firstItem="0fT-vS-7VT" firstAttribute="top" secondItem="Co8-1S-Ok1" secondAttribute="bottom" priority="750" constant="8" id="OBz-ja-4yF"/>
<constraint firstItem="Co8-1S-Ok1" firstAttribute="top" secondItem="JWK-TM-5X8" secondAttribute="top" constant="8" id="ZFJ-F0-dou"/>
<constraint firstItem="JWK-TM-5X8" firstAttribute="trailing" secondItem="0fT-vS-7VT" secondAttribute="trailing" constant="8" id="cIW-BW-3pC"/>
<constraint firstItem="0fT-vS-7VT" firstAttribute="top" relation="greaterThanOrEqual" secondItem="Co8-1S-Ok1" secondAttribute="bottom" constant="8" id="fA0-tw-Go1"/>
<constraint firstItem="JWK-TM-5X8" firstAttribute="bottom" secondItem="0fT-vS-7VT" secondAttribute="bottom" constant="8" id="o37-Gn-NnO"/>
<constraint firstItem="Co8-1S-Ok1" firstAttribute="leading" secondItem="JWK-TM-5X8" secondAttribute="leading" constant="8" id="oZC-Iy-oyX"/>
<constraint firstItem="JWK-TM-5X8" firstAttribute="trailing" secondItem="Co8-1S-Ok1" secondAttribute="trailing" constant="8" id="tcy-Gi-3g3"/>
<constraint firstItem="0fT-vS-7VT" firstAttribute="leading" secondItem="JWK-TM-5X8" secondAttribute="leading" constant="8" id="zW4-Hf-Mdc"/>
</constraints>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<point key="canvasLocation" x="283.19999999999999" y="14.842578710644679"/>
</view>
</objects>
<resources>
<systemColor name="labelColor">
<color white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
<systemColor name="systemYellowColor">
<color red="1" green="0.80000000000000004" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</systemColor>
</resources>
</document>