iosswiftxcodestoryboard

Keep the Stackview's content aspect ratio while limiting Stackview's height


I want to show a YouTube video cover (with an aspect ratio of 16:9) in the center of the top half of the screen with respect to the device's orientation. How can I achieve it in the Xcode storyboard?

what I have done so far:

  1. added a Stack view and adjusted it in the top half of the safe area.
  2. Set the alignment to center
  3. Set the content mode to Aspect Fit
  4. added a UIView to the stack view
  5. set the aspect ratio

What I want: enter image description here

What's the point of StackView? I'm trying to limit the height of the child view while keeping the aspect ratio using "Aspect Fit" content mode.


Solution

  • No need for a stack view....

    Let's create a UIView with a red background -this will be your video view (or a "holder" for it):

    let v16x9 = UIView()
    v16x9.backgroundColor = .red
        
    v16x9.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(v16x9)
    

    To cut down on typing, declare the safe area:

    let g = view.safeAreaLayoutGuide
    

    Now the constraints:

    NSLayoutConstraint.activate([
        // top to top of safe area
        v16x9.topAnchor.constraint(equalTo: g.topAnchor),
        // center horizontally
        v16x9.centerXAnchor.constraint(equalTo: g.centerXAnchor),
        // keep the width less-than-or-equal-to the safe area
        v16x9.widthAnchor.constraint(lessThanOrEqualTo: g.widthAnchor),
        // view height is 16:9 ratio
        v16x9.heightAnchor.constraint(equalTo: v16x9.widthAnchor, multiplier: 9.0 / 16.0),
        // keep height less-than-or-equal-to one-half (50%) of the safe area
        v16x9.heightAnchor.constraint(lessThanOrEqualTo: g.heightAnchor, multiplier: 0.5),
    ])
    
    // stretch the view as wide as possible, while respecting the other constraint restrictions
    let wc: NSLayoutConstraint = v16x9.widthAnchor.constraint(equalTo: g.widthAnchor)
    wc.priority = .defaultHigh
    wc.isActive = true
    

    Edit

    To set this up in Storyboard, follow the comments as instructions.

    enter image description here

    Here's the source of that Storyboard:

    <?xml version="1.0" encoding="UTF-8"?>
    <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="22154" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
        <device id="retina6_12" 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>
        <scenes>
            <!--View Controller-->
            <scene sceneID="s0d-6b-0kx">
                <objects>
                    <viewController id="Y6W-OH-hqX" sceneMemberID="viewController">
                        <view key="view" contentMode="scaleToFill" id="5EZ-qb-Rvc">
                            <rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
                            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                            <subviews>
                                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="CLw-Ba-ZZk" userLabel="RedUIView">
                                    <rect key="frame" x="0.0" y="59" width="393" height="221"/>
                                    <color key="backgroundColor" systemColor="systemRedColor"/>
                                    <constraints>
                                        <constraint firstAttribute="width" secondItem="CLw-Ba-ZZk" secondAttribute="height" multiplier="16:9" id="D78-kc-JCT"/>
                                    </constraints>
                                </view>
                            </subviews>
                            <viewLayoutGuide key="safeArea" id="vDu-zF-Fre"/>
                            <color key="backgroundColor" systemColor="systemBackgroundColor"/>
                            <constraints>
                                <constraint firstItem="CLw-Ba-ZZk" firstAttribute="width" secondItem="vDu-zF-Fre" secondAttribute="width" priority="750" id="AN4-IG-kQf"/>
                                <constraint firstItem="CLw-Ba-ZZk" firstAttribute="centerX" secondItem="5EZ-qb-Rvc" secondAttribute="centerX" id="NHW-cs-7a0"/>
                                <constraint firstItem="CLw-Ba-ZZk" firstAttribute="width" relation="lessThanOrEqual" secondItem="vDu-zF-Fre" secondAttribute="width" id="PNx-hV-q3d"/>
                                <constraint firstItem="CLw-Ba-ZZk" firstAttribute="height" relation="lessThanOrEqual" secondItem="vDu-zF-Fre" secondAttribute="height" multiplier="0.5" id="mbh-I7-eel"/>
                                <constraint firstItem="CLw-Ba-ZZk" firstAttribute="top" secondItem="vDu-zF-Fre" secondAttribute="top" id="rfH-ZU-ocg"/>
                            </constraints>
                        </view>
                    </viewController>
                    <placeholder placeholderIdentifier="IBFirstResponder" id="Ief-a0-LHa" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
                </objects>
                <point key="canvasLocation" x="-21" y="5"/>
            </scene>
        </scenes>
        <resources>
            <systemColor name="systemBackgroundColor">
                <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
            </systemColor>
            <systemColor name="systemRedColor">
                <color red="1" green="0.23137254901960785" blue="0.18823529411764706" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
            </systemColor>
        </resources>
    </document>