如何使用具有不同对齐方式的子视图制作堆栈视图?
How to make a stack view with subviews that has different alignments?
我的目标
我正在制作一个 UI,上面有一个图像,下面有四个垂直排列的按钮。图像的高度取决于它的宽度,但它不应该太高以至于按钮不够 space。图像定位后,按钮可以填满 space 的其余部分。在水平方向上,图像应尽量占据屏幕的宽度,但按钮的宽度应恒定为 300,并水平居中。我知道这不是本地化的好主意,但我不打算本地化此应用程序。
一张图值1000字:
我只使用堆栈溢出徽标来替换我将要使用的实际图像。我不是在制作与 Stack Overflow 相关的应用程序。
此外,当垂直尺寸 class 紧凑时,图像视图应位于按钮的左侧(按钮仍然垂直排列)。
我想我基本上想要一个堆栈视图,其子视图对齐方式不同——图像视图与“填充”对齐,按钮与“中心”对齐。但是,我不知道该怎么做,所以我尝试使用嵌套堆栈视图来解决这个问题。
重现方式:
外部堆栈视图 top/bottom/leading/trailing 全部固定到 VC 的视图,对齐设置为“填充”,分布设置为“按比例填充”。我选择“按比例填充”是因为我发现如果我使用足够大的图像效果最好。我在外部堆栈视图的轴上添加了一个变体,以便在垂直尺寸 class 紧凑时将其设置为水平。
外部堆栈视图有 2 个排列的子视图 - 图像视图和内部堆栈视图,其分布设置为“填充”,对齐方式设置为“居中”。
内部堆栈视图然后具有这些按钮。每个按钮都有一个恒定的宽度限制。
我认为应该可以完成这项工作。当我 运行 应用程序时,我看到一些“无法满足约束”警告:
(
"<NSLayoutConstraint:0x6000038d2b20 UIButton:0x7f82d250e3c0'BUTTON1'.width == 300 (active)>",
"<NSLayoutConstraint:0x6000038d98b0 'fittingSizeHTarget' UIStackView:0x7f82d250e230.width == 0 (active)>",
"<NSLayoutConstraint:0x6000038d8cd0 'UISV-canvas-connection' UIStackView:0x7f82d250e230.leading == _UILayoutSpacer:0x6000024e01e0'UISV-alignment-spanner'.leading (active)>",
"<NSLayoutConstraint:0x6000038d9130 'UISV-canvas-connection' UIStackView:0x7f82d250e230.centerX == UIButton:0x7f82d250e3c0'BUTTON1'.centerX (active)>",
"<NSLayoutConstraint:0x6000038d8e10 'UISV-spanning-boundary' _UILayoutSpacer:0x6000024e01e0'UISV-alignment-spanner'.leading <= UIButton:0x7f82d250e3c0'BUTTON1'.leading (active)>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x6000038d2b20 UIButton:0x7f82d250e3c0'BUTTON1'.width == 300 (active)>
每个按钮都有一组!除此之外,布局似乎工作正常,但我不知道什么时候这实际上会破坏进一步的东西。
我查看了哪些约束是冲突的,哪些被破坏了。显然有一个 StackView.width = 0 约束与 button1.width = 300 约束冲突,后者被破坏了。我不知道 StackView.width = 0 约束来自哪里,也不知道它指的是哪个堆栈视图:(
如何防止约束被破坏?
如果我的重现步骤不够清楚,这里是 VC:
的故事板代码
<scene sceneID="N06-uN-k0T">
<objects>
<viewController id="BdK-0G-Xl3" userLabel="Probelm VC" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="OpP-9z-h5Y">
<rect key="frame" x="0.0" y="0.0" width="667" height="375"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="fillProportionally" spacingType="standard" translatesAutoresizingMaskIntoConstraints="NO" id="nvX-HI-4ox">
<rect key="frame" x="16" y="16" width="635" height="343"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="soLogo" translatesAutoresizingMaskIntoConstraints="NO" id="1RQ-jl-D6x">
<rect key="frame" x="0.0" y="0.0" width="327" height="343"/>
</imageView>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="fillEqually" alignment="center" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="ROW-bu-Xw7">
<rect key="frame" x="335" y="0.0" width="300" height="343"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" verticalCompressionResistancePriority="1000" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="hpX-JI-GT0">
<rect key="frame" x="0.0" y="0.0" width="300" height="78.5"/>
<color key="backgroundColor" red="0.23137254900000001" green="0.4823529412" blue="0.23137254900000001" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="width" constant="300" id="Ogw-Xr-6DE"/>
</constraints>
<fontDescription key="fontDescription" name="ChalkboardSE-Regular" family="Chalkboard SE" pointSize="52"/>
<state key="normal" title="BUTTON1"/>
</button>
<button opaque="NO" contentMode="scaleToFill" verticalCompressionResistancePriority="1000" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="dJT-f3-AJM">
<rect key="frame" x="0.0" y="88.5" width="300" height="78"/>
<color key="backgroundColor" red="0.23137254900000001" green="0.4823529412" blue="0.23137254900000001" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="width" constant="300" id="AII-kQ-4cH"/>
</constraints>
<fontDescription key="fontDescription" name="ChalkboardSE-Regular" family="Chalkboard SE" pointSize="52"/>
<state key="normal" title="BUTTON2"/>
</button>
<button opaque="NO" contentMode="scaleToFill" verticalCompressionResistancePriority="1000" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="NZx-LS-e5l">
<rect key="frame" x="0.0" y="176.5" width="300" height="78.5"/>
<color key="backgroundColor" red="0.23137254900000001" green="0.4823529412" blue="0.23137254900000001" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="width" constant="300" id="rDS-bU-7lE"/>
</constraints>
<fontDescription key="fontDescription" name="ChalkboardSE-Regular" family="Chalkboard SE" pointSize="52"/>
<state key="normal" title="BUTTON3"/>
</button>
<button opaque="NO" contentMode="scaleToFill" verticalCompressionResistancePriority="1000" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="onC-ie-E6z">
<rect key="frame" x="0.0" y="265" width="300" height="78"/>
<color key="backgroundColor" red="0.23137254900000001" green="0.4823529412" blue="0.23137254900000001" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="width" constant="300" id="4K7-7z-YHF"/>
</constraints>
<fontDescription key="fontDescription" name="ChalkboardSE-Regular" family="Chalkboard SE" pointSize="52"/>
<state key="normal" title="BUTTON4"/>
</button>
</subviews>
</stackView>
</subviews>
<variation key="heightClass=compact" axis="horizontal"/>
</stackView>
</subviews>
<viewLayoutGuide key="safeArea" id="wgl-gV-tap"/>
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="nvX-HI-4ox" firstAttribute="top" secondItem="wgl-gV-tap" secondAttribute="top" constant="16" id="XjW-5g-rZt"/>
<constraint firstItem="nvX-HI-4ox" firstAttribute="leading" secondItem="wgl-gV-tap" secondAttribute="leading" constant="16" id="eYR-DM-EMX"/>
<constraint firstItem="wgl-gV-tap" firstAttribute="trailing" secondItem="nvX-HI-4ox" secondAttribute="trailing" constant="16" id="xhu-Xr-XWi"/>
<constraint firstItem="wgl-gV-tap" firstAttribute="bottom" secondItem="nvX-HI-4ox" secondAttribute="bottom" constant="16" id="z5a-h7-F7G"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="MTA-xX-zRK" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-183" y="865"/>
</scene>
好的 - 根据您发布的图片,我将为您的“徽标图片”使用 2:1
纵横比...
从“基本”布局开始:
限制条件如下:
Outer StackView
属性:
和 Buttons StackView
属性:
在这一点上,我们应该“准备好”使用“纵向”布局。
让我们添加一些特征变化...
要获得此布局:
我们将为 OuterStack 的 Axis 和 Alignment 添加“Width: Any / Height: Compact”:
我们将为 ButtonsStack 的 Alignment 添加“宽度:任意/高度:紧凑”:
如果我们运行那个(iPhone 12 sim),我们得到这个:
我们接近了,但是...我们在调试控制台中收到了一大堆自动布局警告/错误消息。
那是因为(根据我的经验)自动布局需要进行多次“通过”才能全面评估布局,尤其是在将纵横比约束与堆栈视图混合使用时。
为了摆脱它,我们将给图像视图的纵横比约束一个低于要求的值 Priority
:
这实际上允许自动布局在其多个布局过程中打破约束。
这是完整的故事板源代码,因此您可以更仔细地检查事物:
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="2ea-UR-he0">
<device id="retina4_7" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
<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>
<scenes>
<!--View Controller-->
<scene sceneID="Kgd-qU-TMb">
<objects>
<viewController id="2ea-UR-he0" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="oLK-rW-5I7">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="bhh-Ra-9sa" userLabel="OuterStack">
<rect key="frame" x="16" y="16" width="343" height="635"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="soLogo" translatesAutoresizingMaskIntoConstraints="NO" id="zgv-cZ-TeJ">
<rect key="frame" x="0.0" y="0.0" width="343" height="171.5"/>
<constraints>
<constraint firstAttribute="width" secondItem="zgv-cZ-TeJ" secondAttribute="height" multiplier="2:1" priority="750" id="0U3-Il-GO7"/>
</constraints>
</imageView>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="fillEqually" alignment="center" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="bq4-eZ-cNR" userLabel="ButtonsStack">
<rect key="frame" x="0.0" y="171.5" width="343" height="463.5"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="xKR-aa-qSg">
<rect key="frame" x="21.5" y="0.0" width="300" height="108.5"/>
<color key="backgroundColor" red="0.16262620689999999" green="0.55341011289999997" blue="0.26840737460000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="width" constant="300" id="Omy-Kc-rR2"/>
</constraints>
<fontDescription key="fontDescription" name="ChalkboardSE-Regular" family="Chalkboard SE" pointSize="52"/>
<state key="normal" title="Button 1"/>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="KTN-zM-mhK">
<rect key="frame" x="21.5" y="118.5" width="300" height="108.5"/>
<color key="backgroundColor" red="0.16262620689999999" green="0.55341011289999997" blue="0.26840737460000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="width" constant="300" id="7cU-at-nc8"/>
</constraints>
<fontDescription key="fontDescription" name="ChalkboardSE-Regular" family="Chalkboard SE" pointSize="52"/>
<state key="normal" title="Button 2"/>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="jP5-6h-Pb5">
<rect key="frame" x="21.5" y="237" width="300" height="108"/>
<color key="backgroundColor" red="0.16262620689999999" green="0.55341011289999997" blue="0.26840737460000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="width" constant="300" id="9qP-Dd-5pW"/>
</constraints>
<fontDescription key="fontDescription" name="ChalkboardSE-Regular" family="Chalkboard SE" pointSize="52"/>
<state key="normal" title="Button 3"/>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="jhr-47-0CJ">
<rect key="frame" x="21.5" y="355" width="300" height="108.5"/>
<color key="backgroundColor" red="0.16262620689999999" green="0.55341011289999997" blue="0.26840737460000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="width" constant="300" id="c8c-CT-Sz5"/>
</constraints>
<fontDescription key="fontDescription" name="ChalkboardSE-Regular" family="Chalkboard SE" pointSize="52"/>
<state key="normal" title="Button 4"/>
</button>
</subviews>
<variation key="heightClass=compact" alignment="fill"/>
</stackView>
</subviews>
<variation key="heightClass=compact" alignment="center" axis="horizontal"/>
</stackView>
</subviews>
<viewLayoutGuide key="safeArea" id="guT-8A-oyH"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstItem="bhh-Ra-9sa" firstAttribute="leading" secondItem="guT-8A-oyH" secondAttribute="leading" constant="16" id="6me-RD-7Uz"/>
<constraint firstItem="guT-8A-oyH" firstAttribute="trailing" secondItem="bhh-Ra-9sa" secondAttribute="trailing" constant="16" id="7oW-d7-Lhf"/>
<constraint firstItem="guT-8A-oyH" firstAttribute="bottom" secondItem="bhh-Ra-9sa" secondAttribute="bottom" constant="16" id="9Kz-Ok-e52"/>
<constraint firstItem="bhh-Ra-9sa" firstAttribute="top" secondItem="guT-8A-oyH" secondAttribute="top" constant="16" id="DY2-wl-5Y8"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="b0R-on-Vlz" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1055" y="206"/>
</scene>
</scenes>
<resources>
<image name="soLogo" width="230" height="115"/>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
</resources>
</document>
我的目标
我正在制作一个 UI,上面有一个图像,下面有四个垂直排列的按钮。图像的高度取决于它的宽度,但它不应该太高以至于按钮不够 space。图像定位后,按钮可以填满 space 的其余部分。在水平方向上,图像应尽量占据屏幕的宽度,但按钮的宽度应恒定为 300,并水平居中。我知道这不是本地化的好主意,但我不打算本地化此应用程序。
一张图值1000字:
我只使用堆栈溢出徽标来替换我将要使用的实际图像。我不是在制作与 Stack Overflow 相关的应用程序。
此外,当垂直尺寸 class 紧凑时,图像视图应位于按钮的左侧(按钮仍然垂直排列)。
我想我基本上想要一个堆栈视图,其子视图对齐方式不同——图像视图与“填充”对齐,按钮与“中心”对齐。但是,我不知道该怎么做,所以我尝试使用嵌套堆栈视图来解决这个问题。
重现方式:
外部堆栈视图 top/bottom/leading/trailing 全部固定到 VC 的视图,对齐设置为“填充”,分布设置为“按比例填充”。我选择“按比例填充”是因为我发现如果我使用足够大的图像效果最好。我在外部堆栈视图的轴上添加了一个变体,以便在垂直尺寸 class 紧凑时将其设置为水平。
外部堆栈视图有 2 个排列的子视图 - 图像视图和内部堆栈视图,其分布设置为“填充”,对齐方式设置为“居中”。
内部堆栈视图然后具有这些按钮。每个按钮都有一个恒定的宽度限制。
我认为应该可以完成这项工作。当我 运行 应用程序时,我看到一些“无法满足约束”警告:
(
"<NSLayoutConstraint:0x6000038d2b20 UIButton:0x7f82d250e3c0'BUTTON1'.width == 300 (active)>",
"<NSLayoutConstraint:0x6000038d98b0 'fittingSizeHTarget' UIStackView:0x7f82d250e230.width == 0 (active)>",
"<NSLayoutConstraint:0x6000038d8cd0 'UISV-canvas-connection' UIStackView:0x7f82d250e230.leading == _UILayoutSpacer:0x6000024e01e0'UISV-alignment-spanner'.leading (active)>",
"<NSLayoutConstraint:0x6000038d9130 'UISV-canvas-connection' UIStackView:0x7f82d250e230.centerX == UIButton:0x7f82d250e3c0'BUTTON1'.centerX (active)>",
"<NSLayoutConstraint:0x6000038d8e10 'UISV-spanning-boundary' _UILayoutSpacer:0x6000024e01e0'UISV-alignment-spanner'.leading <= UIButton:0x7f82d250e3c0'BUTTON1'.leading (active)>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x6000038d2b20 UIButton:0x7f82d250e3c0'BUTTON1'.width == 300 (active)>
每个按钮都有一组!除此之外,布局似乎工作正常,但我不知道什么时候这实际上会破坏进一步的东西。
我查看了哪些约束是冲突的,哪些被破坏了。显然有一个 StackView.width = 0 约束与 button1.width = 300 约束冲突,后者被破坏了。我不知道 StackView.width = 0 约束来自哪里,也不知道它指的是哪个堆栈视图:(
如何防止约束被破坏?
如果我的重现步骤不够清楚,这里是 VC:
的故事板代码 <scene sceneID="N06-uN-k0T">
<objects>
<viewController id="BdK-0G-Xl3" userLabel="Probelm VC" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="OpP-9z-h5Y">
<rect key="frame" x="0.0" y="0.0" width="667" height="375"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="fillProportionally" spacingType="standard" translatesAutoresizingMaskIntoConstraints="NO" id="nvX-HI-4ox">
<rect key="frame" x="16" y="16" width="635" height="343"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="soLogo" translatesAutoresizingMaskIntoConstraints="NO" id="1RQ-jl-D6x">
<rect key="frame" x="0.0" y="0.0" width="327" height="343"/>
</imageView>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="fillEqually" alignment="center" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="ROW-bu-Xw7">
<rect key="frame" x="335" y="0.0" width="300" height="343"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" verticalCompressionResistancePriority="1000" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="hpX-JI-GT0">
<rect key="frame" x="0.0" y="0.0" width="300" height="78.5"/>
<color key="backgroundColor" red="0.23137254900000001" green="0.4823529412" blue="0.23137254900000001" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="width" constant="300" id="Ogw-Xr-6DE"/>
</constraints>
<fontDescription key="fontDescription" name="ChalkboardSE-Regular" family="Chalkboard SE" pointSize="52"/>
<state key="normal" title="BUTTON1"/>
</button>
<button opaque="NO" contentMode="scaleToFill" verticalCompressionResistancePriority="1000" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="dJT-f3-AJM">
<rect key="frame" x="0.0" y="88.5" width="300" height="78"/>
<color key="backgroundColor" red="0.23137254900000001" green="0.4823529412" blue="0.23137254900000001" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="width" constant="300" id="AII-kQ-4cH"/>
</constraints>
<fontDescription key="fontDescription" name="ChalkboardSE-Regular" family="Chalkboard SE" pointSize="52"/>
<state key="normal" title="BUTTON2"/>
</button>
<button opaque="NO" contentMode="scaleToFill" verticalCompressionResistancePriority="1000" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="NZx-LS-e5l">
<rect key="frame" x="0.0" y="176.5" width="300" height="78.5"/>
<color key="backgroundColor" red="0.23137254900000001" green="0.4823529412" blue="0.23137254900000001" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="width" constant="300" id="rDS-bU-7lE"/>
</constraints>
<fontDescription key="fontDescription" name="ChalkboardSE-Regular" family="Chalkboard SE" pointSize="52"/>
<state key="normal" title="BUTTON3"/>
</button>
<button opaque="NO" contentMode="scaleToFill" verticalCompressionResistancePriority="1000" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="onC-ie-E6z">
<rect key="frame" x="0.0" y="265" width="300" height="78"/>
<color key="backgroundColor" red="0.23137254900000001" green="0.4823529412" blue="0.23137254900000001" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="width" constant="300" id="4K7-7z-YHF"/>
</constraints>
<fontDescription key="fontDescription" name="ChalkboardSE-Regular" family="Chalkboard SE" pointSize="52"/>
<state key="normal" title="BUTTON4"/>
</button>
</subviews>
</stackView>
</subviews>
<variation key="heightClass=compact" axis="horizontal"/>
</stackView>
</subviews>
<viewLayoutGuide key="safeArea" id="wgl-gV-tap"/>
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="nvX-HI-4ox" firstAttribute="top" secondItem="wgl-gV-tap" secondAttribute="top" constant="16" id="XjW-5g-rZt"/>
<constraint firstItem="nvX-HI-4ox" firstAttribute="leading" secondItem="wgl-gV-tap" secondAttribute="leading" constant="16" id="eYR-DM-EMX"/>
<constraint firstItem="wgl-gV-tap" firstAttribute="trailing" secondItem="nvX-HI-4ox" secondAttribute="trailing" constant="16" id="xhu-Xr-XWi"/>
<constraint firstItem="wgl-gV-tap" firstAttribute="bottom" secondItem="nvX-HI-4ox" secondAttribute="bottom" constant="16" id="z5a-h7-F7G"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="MTA-xX-zRK" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-183" y="865"/>
</scene>
好的 - 根据您发布的图片,我将为您的“徽标图片”使用 2:1
纵横比...
从“基本”布局开始:
限制条件如下:
Outer StackView
属性:
和 Buttons StackView
属性:
在这一点上,我们应该“准备好”使用“纵向”布局。
让我们添加一些特征变化...
要获得此布局:
我们将为 OuterStack 的 Axis 和 Alignment 添加“Width: Any / Height: Compact”:
我们将为 ButtonsStack 的 Alignment 添加“宽度:任意/高度:紧凑”:
如果我们运行那个(iPhone 12 sim),我们得到这个:
我们接近了,但是...我们在调试控制台中收到了一大堆自动布局警告/错误消息。
那是因为(根据我的经验)自动布局需要进行多次“通过”才能全面评估布局,尤其是在将纵横比约束与堆栈视图混合使用时。
为了摆脱它,我们将给图像视图的纵横比约束一个低于要求的值 Priority
:
这实际上允许自动布局在其多个布局过程中打破约束。
这是完整的故事板源代码,因此您可以更仔细地检查事物:
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="2ea-UR-he0">
<device id="retina4_7" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
<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>
<scenes>
<!--View Controller-->
<scene sceneID="Kgd-qU-TMb">
<objects>
<viewController id="2ea-UR-he0" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="oLK-rW-5I7">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="bhh-Ra-9sa" userLabel="OuterStack">
<rect key="frame" x="16" y="16" width="343" height="635"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="soLogo" translatesAutoresizingMaskIntoConstraints="NO" id="zgv-cZ-TeJ">
<rect key="frame" x="0.0" y="0.0" width="343" height="171.5"/>
<constraints>
<constraint firstAttribute="width" secondItem="zgv-cZ-TeJ" secondAttribute="height" multiplier="2:1" priority="750" id="0U3-Il-GO7"/>
</constraints>
</imageView>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="fillEqually" alignment="center" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="bq4-eZ-cNR" userLabel="ButtonsStack">
<rect key="frame" x="0.0" y="171.5" width="343" height="463.5"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="xKR-aa-qSg">
<rect key="frame" x="21.5" y="0.0" width="300" height="108.5"/>
<color key="backgroundColor" red="0.16262620689999999" green="0.55341011289999997" blue="0.26840737460000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="width" constant="300" id="Omy-Kc-rR2"/>
</constraints>
<fontDescription key="fontDescription" name="ChalkboardSE-Regular" family="Chalkboard SE" pointSize="52"/>
<state key="normal" title="Button 1"/>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="KTN-zM-mhK">
<rect key="frame" x="21.5" y="118.5" width="300" height="108.5"/>
<color key="backgroundColor" red="0.16262620689999999" green="0.55341011289999997" blue="0.26840737460000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="width" constant="300" id="7cU-at-nc8"/>
</constraints>
<fontDescription key="fontDescription" name="ChalkboardSE-Regular" family="Chalkboard SE" pointSize="52"/>
<state key="normal" title="Button 2"/>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="jP5-6h-Pb5">
<rect key="frame" x="21.5" y="237" width="300" height="108"/>
<color key="backgroundColor" red="0.16262620689999999" green="0.55341011289999997" blue="0.26840737460000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="width" constant="300" id="9qP-Dd-5pW"/>
</constraints>
<fontDescription key="fontDescription" name="ChalkboardSE-Regular" family="Chalkboard SE" pointSize="52"/>
<state key="normal" title="Button 3"/>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="jhr-47-0CJ">
<rect key="frame" x="21.5" y="355" width="300" height="108.5"/>
<color key="backgroundColor" red="0.16262620689999999" green="0.55341011289999997" blue="0.26840737460000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="width" constant="300" id="c8c-CT-Sz5"/>
</constraints>
<fontDescription key="fontDescription" name="ChalkboardSE-Regular" family="Chalkboard SE" pointSize="52"/>
<state key="normal" title="Button 4"/>
</button>
</subviews>
<variation key="heightClass=compact" alignment="fill"/>
</stackView>
</subviews>
<variation key="heightClass=compact" alignment="center" axis="horizontal"/>
</stackView>
</subviews>
<viewLayoutGuide key="safeArea" id="guT-8A-oyH"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstItem="bhh-Ra-9sa" firstAttribute="leading" secondItem="guT-8A-oyH" secondAttribute="leading" constant="16" id="6me-RD-7Uz"/>
<constraint firstItem="guT-8A-oyH" firstAttribute="trailing" secondItem="bhh-Ra-9sa" secondAttribute="trailing" constant="16" id="7oW-d7-Lhf"/>
<constraint firstItem="guT-8A-oyH" firstAttribute="bottom" secondItem="bhh-Ra-9sa" secondAttribute="bottom" constant="16" id="9Kz-Ok-e52"/>
<constraint firstItem="bhh-Ra-9sa" firstAttribute="top" secondItem="guT-8A-oyH" secondAttribute="top" constant="16" id="DY2-wl-5Y8"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="b0R-on-Vlz" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1055" y="206"/>
</scene>
</scenes>
<resources>
<image name="soLogo" width="230" height="115"/>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
</resources>
</document>