1
votes

Im working on a screen (shown below) that utilizes two scroll views. The Vertical scroll view is the base and it has another view within it for all the content. Within that view theres another scroll view that moves horizontally.

So for reference: Scroll view (vertical) -> view -> Scroll view (horizontal)

Another thing to point out is the intrinsic text view within the first scroll view that pulls data from the backend.

The problem Im facing is this: The vertical scroll view allows you to move up and down but it stops based off of whatever height is set. So if I set the height to 1000, it will get to that point but how won't go any further. If the description is longer than that, it gets cut off so

1) how do I adjust the scrollview (vertical) so that he scrolls as far as it needs to in order to display the entire description text? Basically, how do I adjust the height of the scrollview based off of the height of the textview.

The second issue Im facing is the fact that the vertical scrollview works but the horizontal one doesn't. I've used this horizontal scrollview in many other apps with the same constraints (shown below) but never with it being within a vertical scroll view. Now that its there, it won't work while the other works, and vice versa. so,

2) How do I correctly constrain both scroll views so that they work in unison? The vertical scroll view should scroll up and down and whenever I swipe left or right on the horizontal scroll view, it should move correctly as well.

Screen Design

Screen constraints & layout

Screen constraints & layout continued

2
Is The Second Scroll View the one on top, that you want to scroll horizontally? Are you using a textView instead of a label because it needs to be editable?DonMag
Yeah, its the one on top and Idk I just always figured that with the amount of text Its pulling, it should be a text view. So you're saying do a label instead?Vandal
In general, use a textView if you want editing and/or scrolling. Is your goal to have the text scroll vertically, while the "top horizontal" scroll view remains visible? Or should everything scroll vertically? And... I don't see where you're setting any content of the "top horizontal" scroll view?DonMag
Ah okay so how do I set the constraints when theres a label and a scrollview?Vandal

2 Answers

1
votes

It's common to have a horizontal scroll view embedded in a vertical scroll view - you just need to get the constraints set correctly.

Also, using the proper constraints, it's easy to have the scroll view's content control the scrollable area -- without having to calculate and explicitly set the .contentSize.

Here is the layout. The main view background is Pink; the vertical scroll view is Yellow; the horizontal scroll view is Green:

enter image description here

The vertical scroll view is constrained to 0 on all 4 sides, and it's constrained Equal Width and Height to the main view.

The horizontal scroll view is constrained 0 for Leading, Top and Trailing (no Bottom constraint), and a Height constraint of 390, and it's constrained Equal Width to the main view.

The image view is constrained Leading 10 with W/H of 40.

The Title label is constrained to the image view.

The Description Label (number of lines = 0) is constrained Leading to the image view, Width Equal to the vertical scroll view -20 (10 on the left and 10 on the right). And it's constrained 0 on the Bottom. As you add text to the label and its height grows, that will automatically increase the height of the vertical scroll view's scrollable area (its .contentSize).

Here is the result, before and after scrolling:

enter image description here

And, for clarity, how it looks using Debug View Hierarchy:

enter image description here

To help you get it set up correctly, here's the controller class (no sizing code needed - all it's doing is adding text to the label):

class EmbeddedScrollViewController: UIViewController {

    @IBOutlet var descriptionLabel: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()

        // 20 lines of text
        descriptionLabel.text = (1...20).map({ "Line \($0)" }).joined(separator: "\n")

    }
}

and the Storyboard source:

<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14109" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="1GW-r8-dyB">
    <device id="retina4_7" orientation="portrait">
        <adaptation id="fullscreen"/>
    </device>
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14088"/>
        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <scenes>
        <!--Embedded Scroll View Controller-->
        <scene sceneID="EkT-c0-tFZ">
            <objects>
                <viewController id="1GW-r8-dyB" customClass="EmbeddedScrollViewController" customModule="SW4Temp" customModuleProvider="target" sceneMemberID="viewController">
                    <view key="view" contentMode="scaleToFill" id="Mgr-6N-2U6">
                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <subviews>
                            <scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="K2x-mz-KcZ" userLabel="V-Scroll">
                                <rect key="frame" x="0.0" y="20" width="375" height="647"/>
                                <subviews>
                                    <scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Dcg-9m-tlK" userLabel="H-Scroll">
                                        <rect key="frame" x="0.0" y="0.0" width="375" height="390"/>
                                        <subviews>
                                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Upper Left" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="unz-8T-JcR">
                                                <rect key="frame" x="20" y="20" width="82" height="21"/>
                                                <color key="backgroundColor" red="0.45138680930000002" green="0.99309605359999997" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                                <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="Lower Right" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Cdr-yN-9YB">
                                                <rect key="frame" x="500" y="330" width="90.5" height="21"/>
                                                <color key="backgroundColor" red="0.45138680930000002" green="0.99309605359999997" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                                <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="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="qsY-aV-AFa" userLabel="InfoLabel">
                                                <rect key="frame" x="20" y="281" width="320" height="41"/>
                                                <color key="backgroundColor" red="0.45138680930000002" green="0.99309605359999997" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                                <constraints>
                                                    <constraint firstAttribute="width" constant="320" id="g2L-p3-Nt5"/>
                                                </constraints>
                                                <string key="text">To demonstrate Horizontal scrolling,
There is Another Label to the Right ---&gt;</string>
                                                <fontDescription key="fontDescription" type="system" pointSize="17"/>
                                                <nil key="textColor"/>
                                                <nil key="highlightedColor"/>
                                            </label>
                                        </subviews>
                                        <color key="backgroundColor" red="0.45009386540000001" green="0.98132258650000004" blue="0.4743030667" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                        <constraints>
                                            <constraint firstAttribute="height" constant="390" id="2ln-JF-25C"/>
                                            <constraint firstAttribute="bottom" secondItem="Cdr-yN-9YB" secondAttribute="bottom" constant="20" id="C6t-Uu-DXN"/>
                                            <constraint firstItem="Cdr-yN-9YB" firstAttribute="top" secondItem="qsY-aV-AFa" secondAttribute="bottom" constant="8" id="GfU-jw-KzP"/>
                                            <constraint firstItem="Cdr-yN-9YB" firstAttribute="leading" secondItem="qsY-aV-AFa" secondAttribute="trailing" constant="160" id="Q4e-Fl-IEg"/>
                                            <constraint firstAttribute="trailing" secondItem="Cdr-yN-9YB" secondAttribute="trailing" constant="20" id="X5C-nj-47A"/>
                                            <constraint firstItem="unz-8T-JcR" firstAttribute="leading" secondItem="Dcg-9m-tlK" secondAttribute="leading" constant="20" id="cVG-kM-8ZI"/>
                                            <constraint firstItem="qsY-aV-AFa" firstAttribute="leading" secondItem="unz-8T-JcR" secondAttribute="leading" id="pPP-Ko-du2"/>
                                            <constraint firstItem="qsY-aV-AFa" firstAttribute="top" secondItem="unz-8T-JcR" secondAttribute="bottom" constant="240" id="tMx-HW-l2L"/>
                                            <constraint firstItem="unz-8T-JcR" firstAttribute="top" secondItem="Dcg-9m-tlK" secondAttribute="top" constant="20" id="ybo-xk-6LG"/>
                                        </constraints>
                                    </scrollView>
                                    <pageControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" numberOfPages="3" translatesAutoresizingMaskIntoConstraints="NO" id="B7V-nL-rCv">
                                        <rect key="frame" x="121.5" y="353" width="132" height="37"/>
                                        <color key="backgroundColor" red="0.4756349325" green="0.47564673419999998" blue="0.47564041610000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                        <constraints>
                                            <constraint firstAttribute="width" constant="132" id="2ge-VP-yzz"/>
                                        </constraints>
                                    </pageControl>
                                    <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="3cl-Ou-kTu">
                                        <rect key="frame" x="10" y="405" width="40" height="40"/>
                                        <color key="backgroundColor" red="0.0" green="0.58980089430000004" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                        <constraints>
                                            <constraint firstAttribute="width" constant="40" id="E0D-Ed-vVX"/>
                                            <constraint firstAttribute="height" constant="40" id="MFN-Ap-lkV"/>
                                        </constraints>
                                    </imageView>
                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="This Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="1Sf-bC-0yM">
                                        <rect key="frame" x="58" y="415" width="70" height="21"/>
                                        <color key="backgroundColor" red="0.92143100499999997" green="0.92145264149999995" blue="0.92144101860000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                        <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="Description Label" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="MkP-AG-X03">
                                        <rect key="frame" x="10" y="461" width="355" height="20.5"/>
                                        <color key="backgroundColor" red="1" green="0.83234566450000003" blue="0.47320586440000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                        <fontDescription key="fontDescription" type="system" pointSize="17"/>
                                        <nil key="textColor"/>
                                        <nil key="highlightedColor"/>
                                    </label>
                                </subviews>
                                <color key="backgroundColor" red="0.99953407049999998" green="0.98835557699999999" blue="0.47265523669999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                <constraints>
                                    <constraint firstAttribute="bottom" secondItem="MkP-AG-X03" secondAttribute="bottom" constant="8" id="62d-uw-l6l"/>
                                    <constraint firstItem="B7V-nL-rCv" firstAttribute="centerX" secondItem="Dcg-9m-tlK" secondAttribute="centerX" id="6TH-qD-Rpg"/>
                                    <constraint firstItem="Dcg-9m-tlK" firstAttribute="leading" secondItem="K2x-mz-KcZ" secondAttribute="leading" id="8Cm-Zq-jKu"/>
                                    <constraint firstItem="1Sf-bC-0yM" firstAttribute="centerY" secondItem="3cl-Ou-kTu" secondAttribute="centerY" id="D54-Jk-1zW"/>
                                    <constraint firstItem="MkP-AG-X03" firstAttribute="width" secondItem="K2x-mz-KcZ" secondAttribute="width" constant="-20" id="Sk8-fq-0I8"/>
                                    <constraint firstItem="3cl-Ou-kTu" firstAttribute="top" secondItem="Dcg-9m-tlK" secondAttribute="bottom" constant="15" id="XN2-Lz-nQQ"/>
                                    <constraint firstAttribute="trailing" secondItem="Dcg-9m-tlK" secondAttribute="trailing" id="YtO-y4-qn9"/>
                                    <constraint firstItem="MkP-AG-X03" firstAttribute="leading" secondItem="3cl-Ou-kTu" secondAttribute="leading" id="ZM0-3U-XLQ"/>
                                    <constraint firstItem="Dcg-9m-tlK" firstAttribute="top" secondItem="K2x-mz-KcZ" secondAttribute="top" id="fxa-1i-NHa"/>
                                    <constraint firstItem="Dcg-9m-tlK" firstAttribute="width" secondItem="K2x-mz-KcZ" secondAttribute="width" id="l7O-qV-Ja9"/>
                                    <constraint firstItem="3cl-Ou-kTu" firstAttribute="leading" secondItem="K2x-mz-KcZ" secondAttribute="leading" constant="10" id="on9-FW-ZiG"/>
                                    <constraint firstItem="B7V-nL-rCv" firstAttribute="bottom" secondItem="Dcg-9m-tlK" secondAttribute="bottom" id="tbv-ao-adS"/>
                                    <constraint firstItem="1Sf-bC-0yM" firstAttribute="leading" secondItem="3cl-Ou-kTu" secondAttribute="trailing" constant="8" id="wuV-fj-HFV"/>
                                    <constraint firstItem="MkP-AG-X03" firstAttribute="top" secondItem="3cl-Ou-kTu" secondAttribute="bottom" constant="16" id="x4z-IQ-o2z"/>
                                </constraints>
                            </scrollView>
                        </subviews>
                        <color key="backgroundColor" red="1" green="0.1857388616" blue="0.57339501380000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                        <constraints>
                            <constraint firstItem="MMC-8B-qcF" firstAttribute="trailing" secondItem="K2x-mz-KcZ" secondAttribute="trailing" id="3S9-mL-Ldn"/>
                            <constraint firstItem="MMC-8B-qcF" firstAttribute="bottom" secondItem="K2x-mz-KcZ" secondAttribute="bottom" id="7g2-ph-w0I"/>
                            <constraint firstItem="K2x-mz-KcZ" firstAttribute="top" secondItem="MMC-8B-qcF" secondAttribute="top" id="PIT-lg-Z3r"/>
                            <constraint firstItem="K2x-mz-KcZ" firstAttribute="leading" secondItem="MMC-8B-qcF" secondAttribute="leading" id="irI-yU-v4c"/>
                        </constraints>
                        <viewLayoutGuide key="safeArea" id="MMC-8B-qcF"/>
                    </view>
                    <connections>
                        <outlet property="descriptionLabel" destination="MkP-AG-X03" id="4xr-iw-3tF"/>
                    </connections>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="gbQ-wO-etq" userLabel="First Responder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="41" y="2257"/>
        </scene>
    </scenes>
</document>
1
votes

I would use a CollecttionView or tableView and then put a CollectionView in the cell that you want horizontal scrolling.

You can resize the cell containing the textview in different ways