Reputation: 4023
I want to have a scroll view that displays all of my things in a stack view vertically.
contentView
within the scroll view which contains the stack view, which means I now have view
-> scrollView
-> contentView
-> stackView
.This doesn't scroll.
I tried following this SO answer:
Content Layout Guides
and applied the contentView
's constraints to be 0,0,0,0 to all 4 sides and center it horizontally and vertically to the scroll view.view
(not the scroll view).This only scrolls a little bit, but doesn't fully scroll the bottom. Much of the view is just hidden outside of the screen.
I also tried getting rid of contentView
all together and pinned my stack view to either the scroll view or to view
directly, but none worked.
Finally, I tried this super hacky-looking solution:
override func viewWillLayoutSubviews(){
super.viewWillLayoutSubviews()
scrollView.contentSize = CGSize(width: view.bounds.width, height: view.bounds.height+300)
}
but, it squishes the stack view vertically and doesn't display the content fully.
P.S. I'm adding the constraints for the stack view programmatically:
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true
stackView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor).isActive = true
stackView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
stackView.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
Upvotes: 0
Views: 1669
Reputation: 77462
Here's an example that will work - see if you can figure out what you may have done differently.
Instead of using a "content view" we'll just add the stack view directly to the scroll view via code.
Here's the Storyboard layout:
Here's the source for the Storyboard, so you can examine it directly:
<?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" initialViewController="dVO-AO-rAX">
<device id="retina3_5" orientation="portrait" appearance="light"/>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16087"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Kevvv View Controller-->
<scene sceneID="e7x-2X-Pdg">
<objects>
<viewController id="dVO-AO-rAX" customClass="KevvvViewController" customModule="MiniScratch" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="ZMq-2S-yNo">
<rect key="frame" x="0.0" y="0.0" width="320" height="480"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="bEj-BB-5lU">
<rect key="frame" x="0.0" y="44" width="320" height="402"/>
<viewLayoutGuide key="contentLayoutGuide" id="VmC-Gj-CCr"/>
<viewLayoutGuide key="frameLayoutGuide" id="HBJ-Ua-m26"/>
</scrollView>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<constraints>
<constraint firstItem="bEj-BB-5lU" firstAttribute="leading" secondItem="goZ-oS-cQl" secondAttribute="leading" id="Jwq-Tg-wRK"/>
<constraint firstItem="goZ-oS-cQl" firstAttribute="bottom" secondItem="bEj-BB-5lU" secondAttribute="bottom" constant="34" id="bHJ-DL-1xi"/>
<constraint firstItem="bEj-BB-5lU" firstAttribute="trailing" secondItem="goZ-oS-cQl" secondAttribute="trailing" id="gIL-OY-ENf"/>
<constraint firstItem="bEj-BB-5lU" firstAttribute="top" secondItem="goZ-oS-cQl" secondAttribute="top" constant="44" id="zAh-qk-82E"/>
</constraints>
<viewLayoutGuide key="safeArea" id="goZ-oS-cQl"/>
</view>
<connections>
<outlet property="scrollView" destination="bEj-BB-5lU" id="jYI-Wh-d6w"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="ieG-NN-t0K" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="136.875" y="105"/>
</scene>
</scenes>
</document>
And here's example code that will add a stack view to the scroll view, add 40 labels to the stack view, and then properly constrain the stack view to the scroll view:
class KevvvViewController: UIViewController {
@IBOutlet var scrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
let stack = UIStackView()
stack.axis = .vertical
stack.spacing = 12
stack.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(stack)
for i in 1...40 {
let v = UILabel()
v.backgroundColor = .yellow
v.text = "Label \(i)"
stack.addArrangedSubview(v)
}
NSLayoutConstraint.activate([
stack.topAnchor.constraint(equalTo: scrollView.contentLayoutGuide.topAnchor),
stack.leadingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.leadingAnchor),
stack.trailingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.trailingAnchor),
stack.bottomAnchor.constraint(equalTo: scrollView.contentLayoutGuide.bottomAnchor),
stack.widthAnchor.constraint(equalTo: scrollView.frameLayoutGuide.widthAnchor),
])
// to make it easy to see the scroll view frame
scrollView.backgroundColor = .cyan
}
}
Result, after scrolling down to the 17th label (iPhone 8):
Upvotes: 1
Reputation: 8327
It seems that you only need a UIScrollView
and a UIStackView
like that:
Both UIScrollView
and UIStackView
have set the top, bottom, leading and trailing constraints to their respective superviews. The only difference is the last constraint, between the UIStackView
's width and the Safe Area
width. (this depends on what width do you want the UIStackView
to have)
You may also need to set UIStackView
's Distribution
to something like Equal Spacing
to make sure that always expands depending on its content.
Also, add something in the UIStackView
so that the auto layout stops complaining. (avoid red constraints on the interface builder)
Give it a shot.
Upvotes: 0