Align items in horizontal UIStackView from the center
Set parent UIStackView (vertical stackView) alignment to center.
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:
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:
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:
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
:
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:
Here is how the structure looks in Storyboard:
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
Switching a @State Property to a @Binding Property Interferes with Animation
How to Trigger Xcode's 'Update to Latest Package Versions' from Command Line
Swift Change the Tableviewcell Border Color According to Data
Command Failed Due to Signal: Segmentation Fault: 11 While Emitting Ir Sil Function
Migration from Swift 3 to Swift 4 - Cannot Convert String to Expected String.Element
Treat a Single Integer Value as a Range in Swift
Trying to Add a Protocol to a Class Signature in Swift
Calling Stop() on Avaudioplayernode After Finished Playing Causes Crash
How to Pass Image Value to The Imageslideshow Using Swift
Color Keying Video with Gpuimage on a Scnplane in Arkit
Unresponsive Uibutton in Subview Added to Uistackview
How to Split a String into a [String] and Not [Substring]
How to Detect Text View Begin Editing and End Editing in Swift 3
Generic Method Override Not Working in Swift
Swiftui View Does Not Updated When Observedobject Changed
How to Decode the Body of an Error in Alamofire 5
Why Are Objects in the Same Sknode Layer Not Interacting with Each Other