微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使UIStackView拥抱其内容

如何解决使UIStackView拥抱其内容

我正在尝试使用水平的主UIStackView和垂直的2个子级UIStackViews来实现基本布局。

enter image description here

这就是我想要的:

  • 红色视图有2个约束:width = height = 50
  • 左侧垂直堆栈视图(带有绿色标签)应与最大子视图一样宽,并且应使所有子视图水平居中。
  • 右侧垂直堆栈视图(带有黄色标签)应占据所有可用空间。

将左侧垂直堆栈的对齐方式设置为fill会展开黄色标签,但确实会使红色和绿色视图具有相同的宽度。将对齐方式更改为center可使左侧堆栈不拥抱其子级(就像图片中一样)。

enter image description here

有什么想法应该怎么做?

解决方法

问题是带有UIStackView的垂直Alignment: Center没有固有宽度。

要获得所需的布局,您需要将RedView嵌入到透明的UIView或另一个堆栈视图中,并将其对齐方式设置为Center。

以下是使用堆栈视图的方法,因为与“容器”视图相比,我们需要的约束要少一些:

enter image description here

由于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

最后一项必要设置-绿色标签需要拥抱其内容并抵抗压缩:

enter image description here

结果(标签中有几个不同的字符串)

enter image description here

以下是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>

这是我用来产生上面显示的输出的示例代码:

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",["Longer Green Label",["Green Label","Yellow Label with too much text to fit here."],"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 (紫色)中放置了垂直堆叠视图,然后将其嵌入在带有黄色标签水平堆栈视图中。我将分布设置为等间距,且间距为0 ,这样就不会有间距。

我将左垂直堆栈视图的所有边的约束设置为0(这样,左垂直堆栈视图将采用整个紫色的UIView)。还将 alignment (对齐方式)设置为 center (居中),以使子视图在水平方向居中。

左垂直堆栈视图内部,我为尾随,前导和底部添加了约束0 ,以便使左堆栈视图与最大的子项(绿色标签)一样“宽”。我将标签文本更改为居中,以使文本位于中心。

希望这能回答您的问题!

Check the image here

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。