[英]How to make horizontal UIStackView wrap height content with UIImageView as its children?
[英]Make UIStackView hug its content
问题是带有Alignment: Center
的垂直UIStackView
没有固有宽度。
要获得所需的布局,您需要将 RedView 嵌入到清晰的UIView
或另一个堆栈视图中,并将其 alignment 设置为 Center。
这是堆栈视图的方法,因为我们需要的约束比“容器”视图少:
由于 RedView 具有宽度和高度限制,因此它将始终为50 x 50
。
“外部”堆栈视图 - HorizontalStack
- 被限制在所有四个边上,具有 8 点“填充”。 它的属性是:
Axis: Horizontal
Alignment: Center
Distribution: Fill
Spacing: 0
LeftVerticalStack
属性为:
Axis: Vertical
Alignment: Fill
Distribution: Fill
Spacing: 0
RedContainerStack
属性是:
Axis: Vertical
Alignment: Center
Distribution: Fill
Spacing: 0
最后一项必要设置 - 绿色 Label 需要拥抱其内容并抵抗压缩:
结果(标签中有几个不同的字符串):
这是MyCollCell.xib
的来源:
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="16096" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16087"/>
<capability name="collection view cell content view" 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"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="Cell" id="p9p-j5-QAK" customClass="MyCollCell" customModule="TableAdd" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="309" height="122"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<collectionViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" id="7Um-4C-5Kc">
<rect key="frame" x="0.0" y="0.0" width="309" height="122"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" alignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="Ezy-2A-s1y" userLabel="HorizontalStack">
<rect key="frame" x="8" y="8" width="293" height="106"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="63E-WY-6Uf" userLabel="LeftVerticalStack">
<rect key="frame" x="0.0" y="18" width="92.5" height="70.5"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="HgJ-l5-geV" userLabel="RedContainerStack">
<rect key="frame" x="0.0" y="0.0" width="92.5" height="50"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="od9-kp-hKh" userLabel="RedView">
<rect key="frame" x="21.5" y="0.0" width="50" height="50"/>
<color key="backgroundColor" red="0.90437477830000002" green="0.1580897272" blue="0.20071530339999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="height" constant="50" id="R5P-yj-c9R"/>
<constraint firstAttribute="width" constant="50" id="zOV-Xo-aVe"/>
</constraints>
</view>
</subviews>
</stackView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="1000" verticalHuggingPriority="251" horizontalCompressionResistancePriority="1000" text="Green Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="xzN-ta-GJB">
<rect key="frame" x="0.0" y="50" width="92.5" height="20.5"/>
<color key="backgroundColor" red="0.1673075259" green="0.65853333469999997" blue="0.26840484139999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Yellow Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ReT-76-3Fl">
<rect key="frame" x="92.5" y="43" width="200.5" height="20.5"/>
<color key="backgroundColor" red="0.99657744169999996" green="0.79237681630000001" blue="0.0001898294868" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<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="Ezy-2A-s1y" secondAttribute="trailing" constant="8" id="FlO-FQ-5GG"/>
<constraint firstItem="Ezy-2A-s1y" firstAttribute="top" secondItem="7Um-4C-5Kc" secondAttribute="top" constant="8" id="ct6-Mf-RVp"/>
<constraint firstAttribute="bottom" secondItem="Ezy-2A-s1y" secondAttribute="bottom" constant="8" id="dsT-ps-AIz"/>
<constraint firstItem="Ezy-2A-s1y" firstAttribute="leading" secondItem="7Um-4C-5Kc" secondAttribute="leading" constant="8" id="wAj-T5-Vzs"/>
</constraints>
</collectionViewCellContentView>
<size key="customSize" width="309" height="122"/>
<connections>
<outlet property="greenLabel" destination="xzN-ta-GJB" id="1Tu-hu-JOb"/>
<outlet property="yellowLabel" destination="ReT-76-3Fl" id="zTt-ML-CsA"/>
</connections>
<point key="canvasLocation" x="165.94202898550725" y="145.98214285714286"/>
</collectionViewCell>
</objects>
</document>
这是我用来生成上面显示的 output 的示例代码:
import UIKit
private let reuseIdentifier = "Cell"
// cell sizing extension and systemLayoutSizeFitting implementation
// is not mine, but can be found here:
// https://www.robertpieta.com/autosizing-full-width-cells/
extension UICollectionView {
var widestCellWidth: CGFloat {
let insets = contentInset.left + contentInset.right
return bounds.width - insets
}
}
class MyCollCell: UICollectionViewCell {
@IBOutlet var greenLabel: UILabel!
@IBOutlet var yellowLabel: UILabel!
override func systemLayoutSizeFitting(
_ targetSize: CGSize,
withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority,
verticalFittingPriority: UILayoutPriority) -> CGSize {
// Replace the height in the target size to
// allow the cell to flexibly compute its height
var targetSize = targetSize
targetSize.height = CGFloat.greatestFiniteMagnitude
// The .required horizontal fitting priority means
// the desired cell width (targetSize.width) will be
// preserved. However, the vertical fitting priority is
// .fittingSizeLevel meaning the cell will find the
// height that best fits the content
let size = super.systemLayoutSizeFitting(
targetSize,
withHorizontalFittingPriority: .required,
verticalFittingPriority: .fittingSizeLevel
)
return size
}
}
class MyCollectionViewController: UICollectionViewController {
let myData: [[String]] = [
["Green Label", "Yellow Label"],
["G", "Yellow Label"],
["Longer Green Label", "Yellow Label"],
["Green Label", "Yellow Label with too much text to fit here."],
["Green Label", "Yellow Label with .numberOfLines set to 0 will wrap when there's too much text."],
]
override func viewDidLoad() {
super.viewDidLoad()
// Register cell classes
self.collectionView.register(UINib(nibName: "MyCollCell", bundle: nil), forCellWithReuseIdentifier: reuseIdentifier)
let layout = collectionView.collectionViewLayout
if let flowLayout = layout as? UICollectionViewFlowLayout {
flowLayout.estimatedItemSize = CGSize(
width: collectionView.widestCellWidth,
// Make the height a reasonable estimate to
// ensure the scroll bar remains smooth
height: 100
)
}
}
// MARK: UICollectionViewDataSource
override func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return myData.count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! MyCollCell
cell.greenLabel.text = myData[indexPath.row][0]
cell.yellowLabel.text = myData[indexPath.row][1]
cell.yellowLabel.numberOfLines = indexPath.item == 4 ? 0 : 1
return cell
}
}
参考我在下面上传的照片,我将左侧垂直堆栈视图放在UIView (紫色)中,然后用黄色 label将它们嵌入到水平堆栈视图中。 我将分布设置为等间距,间距为 0 ,这样就不会有间距。
我将左侧垂直堆栈视图的所有边的约束设置为 0(这样左侧垂直堆栈视图将占据整个紫色 UIView)。 将alignment也设置为居中,以便子视图水平居中。
在左侧垂直堆栈视图中,我为尾随、前导和底部添加了0 约束,以便左侧堆栈视图与最大的子视图(即绿色标签)一样“宽”。 我将 label 文本更改为居中,使文本居中。
希望这能回答你的问题!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.