繁体   English   中英

让 UIStackView 拥抱它的内容

[英]Make UIStackView hug its content

我正在尝试使用主要水平UIStackView实现基本布局,并带有 2 个子垂直UIStackViews

在此处输入图像描述

这是我想要的:

  • 红色视图有 2 个约束:宽度 = 高度 = 50
  • 左侧垂直堆栈视图(带有绿色标签)应该与其最大的孩子一样宽,并且应该水平居中所有孩子。
  • 正确的垂直堆栈视图(带有黄色标签)应该占用所有可用空间。

将左侧垂直堆栈的 alignment 设置为fill会扩展黄色 label,但这样做会使红色和绿色视图具有相同的宽度。 将 alignment 更改为center ,使左侧堆栈不会拥抱它的孩子(就像在图像中一样)。

在此处输入图像描述

有什么想法应该怎么做?

问题是带有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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM