-2

I have the following setup

            Top View
               |
               |
 LeftView -- MyView --- RightView
               |
               |
          BottomView

I want MyView to have largest possible frame with aspect ratio 1:1 and should respect boundary condition of not crossing any of the 4 views (Left View, Right View, Top View, Bottom View). How do I express autolayout constraints, preferably in Storyboard?

Deepak Sharma
  • 5,577
  • 7
  • 55
  • 131
  • What are the specifics of the outer views? – André Slotta May 12 '19 at 13:24
  • 1
    I created a Swift 3 repo 2 years ago for centering a 1:1 view in any screen. I just updated it to Swift 5 at https://github.com/justdfd/Square-Swift5 I could do the work to replace the "margins" with actual views, but I'm thinking it would be better for you to - learning moment and all. Basically I think you need to add a few more constraints than I have - I have **two** constraints for each centered view aspect, one **<+** and one **=** with a lower priority - and these need to be similar but with the surrounding views. Bottom line? Multiple constraints wish different priorities. –  May 12 '19 at 17:07
  • How do I center MyView using your solution (without using superview solution suggested by Andre)? – Deepak Sharma May 13 '19 at 07:22
  • @DeepakSharma - Do you want `MyView` centered on the superView? Or centered between Left/Right Top/Bottom views? In other words, if `LeftVIew` is 40-pts wide, and `RightView` is 100-pts wide, do you want the Center of `MyView` to be at the center of the superVIew -- which puts a larger space between it and the `LeftView` and a smaller space between it and the `RightView`? Or should it be left-of-center of the center of superView, and equally centered between Left/Right? – DonMag May 13 '19 at 12:00
  • Want it to be centered between left/Right and top/bottom. Views can be of different sizes. – Deepak Sharma May 13 '19 at 12:15

3 Answers3

1

Use a regular UIView as a container (parent) for MyView (this is required for correct centering). Then use the following constraints:

  1. Pin the container view to the top, leading, bottom and trailing views with a spacing of 0.
  2. Center MyView horizontally and vertically in the container view.
  3. Pin MyView to the top, leading, bottom and trailing of the container view with whatever spacing you wish and non required priorities (e.g. 750).
  4. Again pin MyView to the top, leading, bottom and trailing of the container with whatever spacing you wish. This time make all four contraints required and greater than.
  5. Set the aspect ratio for MyView to whatever you wish.

Result: result

André Slotta
  • 13,774
  • 2
  • 22
  • 34
0

"Distance between elements" constraints cannot be set equal or proportional to each other.

So you have a couple options, with the most straight-forward and easiest (in my view) being to use a "container view" to hold "MyView"

Start by adding your Top/Bottom and Left/Right views. I've set them with these width/height constraints to demonstrate. Constrain them Top, Leading, Trailing and Bottom, with Top and Bottom centered horizontally and Left and Right centered vertically:

enter image description here

Now add a UIView that we'll use as a "container view" -- I gave it a red background to make it easy to see:

enter image description here

Constrain each side of the container view to each of the other views (Top to Bottom of TopView, Leading to Trailing of LeftView, etc).

If you run the app now, you'll get this result:

enter image description here

enter image description here

So far, nothing special.

Next, add your "MyView" as a subview of the container view... and we're going to get a little tricky with the constraints.

The easy parts:

  • proportional constraint of 1:1
  • constrain it centered vertically and horizontally in container view

Next:

  • add Top/Bottom/Leading/Trailing constraints of ZERO
  • Edit each of those constraints and set their Priority to 750

Now:

  • add another set of Top/Bottom/Leading/Trailing constraints of ZERO
  • Edit each of those constraints and set them to >=

Your Storyboard should look like this:

enter image description here

and, when we run the app:

enter image description here

enter image description here

Here's how it looks when the container view background is set to clear:

enter image description here

enter image description here

As you see, the center "MyView" fills as much space as possible while remaining at a 1:1 ratio, and there is equal spacing Left/Right and Top/Bottom.

If you want a little "padding" between the views, change the constraints of the "container view" relative to each of the Top/Bottom Left/Right views. Here I've changed them from Zero to 8 (no other changes needed)

enter image description here

And, the results:

enter image description here

enter image description here

enter image description here

enter image description here

Finally, here is the source of the Storyboard:

<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="yEI-oI-7TM">
    <device id="retina4_7" orientation="portrait">
        <adaptation id="fullscreen"/>
    </device>
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <scenes>
        <!--View Controller-->
        <scene sceneID="lsW-Jh-u0o">
            <objects>
                <viewController id="yEI-oI-7TM" sceneMemberID="viewController">
                    <view key="view" contentMode="scaleToFill" id="bPW-Lv-D8K">
                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <subviews>
                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="200 x 28" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ufs-Rs-T6p">
                                <rect key="frame" x="87.5" y="20" width="200" height="28"/>
                                <color key="backgroundColor" red="0.45138680930000002" green="0.99309605359999997" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                <constraints>
                                    <constraint firstAttribute="width" constant="200" id="KeC-SC-7sr"/>
                                    <constraint firstAttribute="height" constant="28" id="Snc-pq-7hW"/>
                                </constraints>
                                <fontDescription key="fontDescription" type="system" pointSize="17"/>
                                <nil key="textColor"/>
                                <nil key="highlightedColor"/>
                            </label>
                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ytj-cQ-xcw">
                                <rect key="frame" x="0.0" y="258.5" width="34" height="150"/>
                                <color key="backgroundColor" red="0.45138680930000002" green="0.99309605359999997" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                <constraints>
                                    <constraint firstAttribute="height" constant="150" id="LDr-tW-Ea2"/>
                                    <constraint firstAttribute="width" constant="34" id="jXP-5w-bh0"/>
                                </constraints>
                                <string key="text">34
x
150</string>
                                <fontDescription key="fontDescription" type="system" pointSize="17"/>
                                <nil key="textColor"/>
                                <nil key="highlightedColor"/>
                            </label>
                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="FKr-kC-VXc">
                                <rect key="frame" x="275" y="233.5" width="100" height="200"/>
                                <color key="backgroundColor" red="0.45138680930000002" green="0.99309605359999997" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                <constraints>
                                    <constraint firstAttribute="height" constant="200" id="JX4-TU-YAy"/>
                                    <constraint firstAttribute="width" constant="100" id="lyr-5f-Pkd"/>
                                </constraints>
                                <string key="text">100
x
200</string>
                                <fontDescription key="fontDescription" type="system" pointSize="17"/>
                                <nil key="textColor"/>
                                <nil key="highlightedColor"/>
                            </label>
                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="100 x 100" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Yjf-aU-73z">
                                <rect key="frame" x="137.5" y="567" width="100" height="100"/>
                                <color key="backgroundColor" red="0.45138680930000002" green="0.99309605359999997" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                <constraints>
                                    <constraint firstAttribute="width" constant="100" id="7cd-f4-E5d"/>
                                    <constraint firstAttribute="height" constant="100" id="OJH-rB-ezu"/>
                                </constraints>
                                <fontDescription key="fontDescription" type="system" pointSize="17"/>
                                <nil key="textColor"/>
                                <nil key="highlightedColor"/>
                            </label>
                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="HVg-nR-YS6">
                                <rect key="frame" x="42" y="56" width="225" height="503"/>
                                <subviews>
                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="MyView" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="KKs-Gt-Kdd">
                                        <rect key="frame" x="0.0" y="139" width="225" height="225"/>
                                        <color key="backgroundColor" red="0.0" green="0.58980089430000004" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                        <constraints>
                                            <constraint firstAttribute="width" secondItem="KKs-Gt-Kdd" secondAttribute="height" multiplier="1:1" id="7W6-ga-lno"/>
                                        </constraints>
                                        <fontDescription key="fontDescription" type="system" pointSize="17"/>
                                        <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                        <nil key="highlightedColor"/>
                                    </label>
                                </subviews>
                                <color key="backgroundColor" red="1" green="0.14913141730000001" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                <constraints>
                                    <constraint firstItem="KKs-Gt-Kdd" firstAttribute="centerY" secondItem="HVg-nR-YS6" secondAttribute="centerY" id="1Xx-i7-Ozs"/>
                                    <constraint firstAttribute="trailing" secondItem="KKs-Gt-Kdd" secondAttribute="trailing" priority="750" id="AGs-sc-h0s"/>
                                    <constraint firstItem="KKs-Gt-Kdd" firstAttribute="leading" secondItem="HVg-nR-YS6" secondAttribute="leading" priority="750" id="BpD-Dh-uWw"/>
                                    <constraint firstItem="KKs-Gt-Kdd" firstAttribute="top" secondItem="HVg-nR-YS6" secondAttribute="top" priority="750" id="Cab-k8-rRO"/>
                                    <constraint firstItem="KKs-Gt-Kdd" firstAttribute="top" relation="greaterThanOrEqual" secondItem="HVg-nR-YS6" secondAttribute="top" id="PA2-Kf-ZGk"/>
                                    <constraint firstAttribute="bottom" secondItem="KKs-Gt-Kdd" secondAttribute="bottom" priority="750" id="XAa-gM-AS6"/>
                                    <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="KKs-Gt-Kdd" secondAttribute="trailing" id="ZwM-wh-Yva"/>
                                    <constraint firstItem="KKs-Gt-Kdd" firstAttribute="centerX" secondItem="HVg-nR-YS6" secondAttribute="centerX" id="gcp-tp-2tO"/>
                                    <constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="KKs-Gt-Kdd" secondAttribute="bottom" id="msf-lp-AEL"/>
                                    <constraint firstItem="KKs-Gt-Kdd" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="HVg-nR-YS6" secondAttribute="leading" id="uSX-oQ-rlK"/>
                                </constraints>
                            </view>
                        </subviews>
                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                        <constraints>
                            <constraint firstItem="HVg-nR-YS6" firstAttribute="top" secondItem="ufs-Rs-T6p" secondAttribute="bottom" constant="8" id="0dx-30-jr7"/>
                            <constraint firstItem="tiR-WL-oTG" firstAttribute="trailing" secondItem="FKr-kC-VXc" secondAttribute="trailing" id="9Nc-oP-aij"/>
                            <constraint firstItem="HVg-nR-YS6" firstAttribute="leading" secondItem="ytj-cQ-xcw" secondAttribute="trailing" constant="8" id="JFX-0b-cV0"/>
                            <constraint firstItem="ytj-cQ-xcw" firstAttribute="leading" secondItem="tiR-WL-oTG" secondAttribute="leading" id="KdN-6J-uTP"/>
                            <constraint firstItem="FKr-kC-VXc" firstAttribute="centerY" secondItem="bPW-Lv-D8K" secondAttribute="centerY" id="TZl-s4-qtB"/>
                            <constraint firstItem="ufs-Rs-T6p" firstAttribute="top" secondItem="tiR-WL-oTG" secondAttribute="top" id="Xik-Uy-8Dc"/>
                            <constraint firstItem="Yjf-aU-73z" firstAttribute="top" secondItem="HVg-nR-YS6" secondAttribute="bottom" constant="8" id="dWC-mc-WBd"/>
                            <constraint firstItem="FKr-kC-VXc" firstAttribute="leading" secondItem="HVg-nR-YS6" secondAttribute="trailing" constant="8" id="hvb-za-mJZ"/>
                            <constraint firstItem="Yjf-aU-73z" firstAttribute="centerX" secondItem="bPW-Lv-D8K" secondAttribute="centerX" id="n15-uw-LKo"/>
                            <constraint firstItem="tiR-WL-oTG" firstAttribute="bottom" secondItem="Yjf-aU-73z" secondAttribute="bottom" id="uws-fV-jh6"/>
                            <constraint firstItem="ufs-Rs-T6p" firstAttribute="centerX" secondItem="bPW-Lv-D8K" secondAttribute="centerX" id="zNk-qR-tkB"/>
                            <constraint firstItem="ytj-cQ-xcw" firstAttribute="centerY" secondItem="bPW-Lv-D8K" secondAttribute="centerY" id="zje-ml-TE1"/>
                        </constraints>
                        <viewLayoutGuide key="safeArea" id="tiR-WL-oTG"/>
                    </view>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="DYV-sv-5ip" userLabel="First Responder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="-2338.4000000000001" y="234.33283358320841"/>
        </scene>
    </scenes>
</document>
DonMag
  • 69,424
  • 5
  • 50
  • 86
0

Do you want something like this?

Example

Let me know to edit my answer.

Nick
  • 1,434
  • 1
  • 10
  • 19