Left Aligned Horizontal Stackview and Top Aligned Vertical Stackview

Align items in horizontal UIStackView from the center

Set parent UIStackView (vertical stackView) alignment to center.Sample Image

Displaying property with Horizontal and Vertical Stack View in Swift

The main problem is that you have your .axis properties reversed.

You want your mainStackView.axis to be .horizontal and your stackView.axis to be .vertical.

Also, these two lines are not needed (and cause problems):

// don't do this
//stackView.leadingAnchor.constraint(equalTo: mainStackView.leadingAnchor).isActive = true
//stackView.trailingAnchor.constraint(equalTo: mainStackView.trailingAnchor).isActive = true

As a side note, instead of:

let safeArea = contentView.safeAreaLayoutGuide

you may want to use:

let safeArea = contentView.layoutMarginsGuide

which gives you the default cell margins.


Edit

// this is the "main" stack view with
// the image on the left
// the labels on the right
// so it needs to be HORIZONTAL
private lazy var mainStackView: UIStackView = {
let stackView = UIStackView()
stackView.translatesAutoresizingMaskIntoConstraints = false

//stackView.axis = .vertical
stackView.axis = .horizontal

stackView.distribution = .fill
return stackView
}()

// this is the "labels" stack view with
// two (or more) labels from top down
// so it needs to be VERTICAL
private lazy var stackView: UIStackView = {
let stackView = UIStackView()
stackView.translatesAutoresizingMaskIntoConstraints = false

//stackView.axis = .horizontal
stackView.axis = .vertical

stackView.distribution = .fill
return stackView
}()

Horizontal UIStackView - how to align items inside so that one is floated left and the other sticks in center?

You have a few options...


The simplest, and closest to your CSS description:

Sample Image

Button is constrained 0 from top, 8 from leading (adjust as desired); label is constrained centered vertically to button, centered horizontally to view.

The drawback: if label gets too much text, it will overlap the button.


Second option:

Sample Image

Same as above, but add a "spacer" UIView to upper right... constrain it 0 to top, 8 to trailing, centered vertically to button, and constrain it equal width and equal height to button. Then, add >= 8 constraints to the label leading to button trailing, and label trailing to spacer view leading. That will allow the label to expand horizontally based on its text, but will prevent overlap (text will be ... truncated if there is too much to fit).


Third option - using stack view:

Sample Image

Stack view settings:

Axis: Horizontal
Alignment: Fill
Distribution: Fill
Spacing: 8

Constrain the stack view 0 to top, 8 leading and trailing (just for a little padding on the sides), add a button, label and UIView. Constrain the
"spacer" view equal width to the button. Set the Horizontal Content Hugging Priority = 1000 for the button (will keep it the width of its title).

There are other approaches, partially depending on if you want to do anything else you haven't shown here, but all three of these will do the job.

StackView Not Aligning To The Left Programmatically

Set:

    stackView.alignment = .leading 

And remove This:

    stackView.distribution = .equalSpacing

Your code then will be like:

    cameraButton.setImage(UIImage(named: "blueCamera"), for: .normal)
cameraButton.addTarget(self, action: #selector(cameraTapped), for: .touchUpInside)
cameraButton.widthAnchor.constraint(equalToConstant: 70.0).isActive = true
calenderButton.setImage(UIImage(named: "calender"), for: .normal)
calenderButton.addTarget(self, action: #selector(calanderTapped), for: .touchUpInside)
calenderButton.widthAnchor.constraint(equalToConstant: 70.0).isActive = true

stackView.frame = CGRect(x: 0, y: 0, width: scrollView.frame.size.width, height: scrollViewHeight)
stackView.axis = .horizontal
stackView.spacing = 5
stackView.alignment = .leading
stackView.addArrangedSubview(calenderButton)
stackView.addArrangedSubview(cameraButton)
stackView.backgroundColor = UIColor(red: 0.161, green: 0.165, blue: 0.188, alpha: 1.00)
scrollView.addSubview(stackView)

Problem with Aligning of buttons in Stack View

How you set your stack view properties and constraints, and the button constraints, will depend on exactly what you want as a result.

Take a look at these image - first one includes the Editor -> Canvas -> Bounds Rectangles:

Sample Image

Sample Image

In all three, Button 1 has a 1:1 Ratio constraint.


The Top stack view is constrained Top (40) and Leading and Trailing at 16-pts from the sides. Stack view properties are:

  • Alignment: Fill
  • Distribution: Fill Equally
  • Spacing: Standard

So, the stack view width is the width of the view, minus 32 (16-pts on each side). The stack view automatically gives each button the same width - Fill Equally - and the 1:1 constraint on the first button sets its Height equal to its Width (square), and the rest of the buttons follow suit.


For the Middle example, the stack view is constrained Top (40) and CenterX. Stack view properties are:

  • Alignment: Fill
  • Distribution: Fill Equally
  • Spacing: Standard

The only additional constraint is Button 1 has a Width constraint of 40. So all 6 buttons are 40 x 40, standard spacing between them, and the stack view is centered horizontally.


For the Bottom example, the stack view is constrained Top (40) and Leading and Trailing at 16-pts from the sides. Stack view properties are:

  • Alignment: Fill
  • Distribution: Equal Spacing
  • Spacing: Standard

In addition, Button 1 has a width constraint of 40, and Buttons 2 thru 6 all have Width = Button1.width.

So the stack view width is the width of the view, minus 32 (16-pts on each side). Each button is 40 x 40 (again, the 1:1 ratio on Button 1 keeps them square), and the stack view set the spacing to fill out the width.


You'll want to keep in mind how that will change on different device sizes.

For example, here's how that looks (with NO changes to constraints or properties) when we rotate the device:

Sample Image


Here is how the structure looks in Storyboard:

Sample Image

and here's the source to the Storyboard so you can examine / play with it:

<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="16096" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16087"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="Stack View standard spacing" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="o2J-7j-Hec">
<objects>
<viewController id="qIB-4e-obb" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="Aak-ib-U1S">
<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" distribution="fillEqually" spacingType="standard" translatesAutoresizingMaskIntoConstraints="NO" id="DHB-rx-egj" userLabel="FitWidthStack">
<rect key="frame" x="16" y="40" width="343" height="50.5"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="8Ue-Xm-LQi">
<rect key="frame" x="0.0" y="0.0" width="50.5" height="50.5"/>
<color key="backgroundColor" red="0.55634254220000001" green="0.97934550050000002" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="width" secondItem="8Ue-Xm-LQi" secondAttribute="height" multiplier="1:1" id="IvC-Jh-rdd"/>
</constraints>
<state key="normal" title="1"/>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="R14-hZ-UbE">
<rect key="frame" x="58.5" y="0.0" width="50.5" height="50.5"/>
<color key="backgroundColor" red="0.55634254220000001" green="0.97934550050000002" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<state key="normal" title="2"/>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="syB-R1-vN7">
<rect key="frame" x="117" y="0.0" width="50.5" height="50.5"/>
<color key="backgroundColor" red="0.55634254220000001" green="0.97934550050000002" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<state key="normal" title="3"/>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="f1X-gj-ygM">
<rect key="frame" x="175.5" y="0.0" width="50.5" height="50.5"/>
<color key="backgroundColor" red="0.55634254220000001" green="0.97934550050000002" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<state key="normal" title="4"/>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="fK2-cI-wo3">
<rect key="frame" x="234" y="0.0" width="50.5" height="50.5"/>
<color key="backgroundColor" red="0.55634254220000001" green="0.97934550050000002" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<state key="normal" title="5"/>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="MQX-O8-Tgu">
<rect key="frame" x="292.5" y="0.0" width="50.5" height="50.5"/>
<color key="backgroundColor" red="0.55634254220000001" green="0.97934550050000002" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<state key="normal" title="6"/>
</button>
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacingType="standard" translatesAutoresizingMaskIntoConstraints="NO" id="D9y-7o-SD4" userLabel="CenterXStack">
<rect key="frame" x="47.5" y="130.5" width="280" height="40"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="PVs-vi-HFL">
<rect key="frame" x="0.0" y="0.0" width="40" height="40"/>
<color key="backgroundColor" red="0.55634254220000001" green="0.97934550050000002" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="width" constant="40" id="2tP-1p-WIh"/>
<constraint firstAttribute="width" secondItem="PVs-vi-HFL" secondAttribute="height" multiplier="1:1" id="iph-ol-vl6"/>
</constraints>
<state key="normal" title="1"/>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Zam-9o-U4q">
<rect key="frame" x="48" y="0.0" width="40" height="40"/>
<color key="backgroundColor" red="0.55634254220000001" green="0.97934550050000002" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<state key="normal" title="2"/>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Fdn-MX-Ivu">
<rect key="frame" x="96" y="0.0" width="40" height="40"/>
<color key="backgroundColor" red="0.55634254220000001" green="0.97934550050000002" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<state key="normal" title="3"/>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="dhX-aw-ohs">
<rect key="frame" x="144" y="0.0" width="40" height="40"/>
<color key="backgroundColor" red="0.55634254220000001" green="0.97934550050000002" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<state key="normal" title="4"/>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="nJO-xF-B3Y">
<rect key="frame" x="192" y="0.0" width="40" height="40"/>
<color key="backgroundColor" red="0.55634254220000001" green="0.97934550050000002" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<state key="normal" title="5"/>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="JZ6-Lc-yzW">
<rect key="frame" x="240" y="0.0" width="40" height="40"/>
<color key="backgroundColor" red="0.55634254220000001" green="0.97934550050000002" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<state key="normal" title="6"/>
</button>
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" distribution="equalSpacing" spacingType="standard" translatesAutoresizingMaskIntoConstraints="NO" id="2eO-xS-xt7" userLabel="EqualSpacingStack">
<rect key="frame" x="16" y="210.5" width="343" height="40"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="5OX-TX-zzE">
<rect key="frame" x="0.0" y="0.0" width="40" height="40"/>
<color key="backgroundColor" red="0.55634254220000001" green="0.97934550050000002" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="width" constant="40" id="FaE-ZG-cnh"/>
<constraint firstAttribute="width" secondItem="5OX-TX-zzE" secondAttribute="height" multiplier="1:1" id="yEH-j6-Ikc"/>
</constraints>
<state key="normal" title="1"/>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="vy5-wT-KZg">
<rect key="frame" x="60.5" y="0.0" width="40" height="40"/>
<color key="backgroundColor" red="0.55634254220000001" green="0.97934550050000002" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<state key="normal" title="2"/>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="xIu-el-0yH">
<rect key="frame" x="121" y="0.0" width="40" height="40"/>
<color key="backgroundColor" red="0.55634254220000001" green="0.97934550050000002" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<state key="normal" title="3"/>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Suq-hc-eDl">
<rect key="frame" x="182" y="0.0" width="40" height="40"/>
<color key="backgroundColor" red="0.55634254220000001" green="0.97934550050000002" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<state key="normal" title="4"/>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="hP2-U2-MNf">
<rect key="frame" x="242.5" y="0.0" width="40" height="40"/>
<color key="backgroundColor" red="0.55634254220000001" green="0.97934550050000002" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<state key="normal" title="5"/>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="kb1-3H-bP7">
<rect key="frame" x="303" y="0.0" width="40" height="40"/>
<color key="backgroundColor" red="0.55634254220000001" green="0.97934550050000002" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<state key="normal" title="6"/>
</button>
</subviews>
<constraints>
<constraint firstItem="kb1-3H-bP7" firstAttribute="width" secondItem="5OX-TX-zzE" secondAttribute="width" id="AMt-Sm-61b"/>
<constraint firstItem="Suq-hc-eDl" firstAttribute="width" secondItem="5OX-TX-zzE" secondAttribute="width" id="Exj-gK-x8q"/>
<constraint firstItem="hP2-U2-MNf" firstAttribute="width" secondItem="5OX-TX-zzE" secondAttribute="width" id="mKn-cn-wIQ"/>
<constraint firstItem="vy5-wT-KZg" firstAttribute="width" secondItem="5OX-TX-zzE" secondAttribute="width" id="rNn-Ua-n1n"/>
<constraint firstItem="xIu-el-0yH" firstAttribute="width" secondItem="5OX-TX-zzE" secondAttribute="width" id="vJn-JR-owY"/>
</constraints>
</stackView>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<constraints>
<constraint firstItem="aBq-0M-X4Y" firstAttribute="trailing" secondItem="DHB-rx-egj" secondAttribute="trailing" constant="16" id="OcR-HJ-Rx7"/>
<constraint firstItem="D9y-7o-SD4" firstAttribute="top" secondItem="DHB-rx-egj" secondAttribute="bottom" constant="40" id="b2A-fw-h9B"/>
<constraint firstItem="aBq-0M-X4Y" firstAttribute="trailing" secondItem="2eO-xS-xt7" secondAttribute="trailing" constant="16" id="jTT-lY-SsV"/>


Related Topics



Leave a reply



Submit