Search code examples
iosswiftuiviewuiscrollviewuitextview

Adjust size of UIView inside UIScrollView according to its content


I have such layout hierarchy inside of the root UIView (see the picture): UIScrollView -> UIView -> UITextView

I change the size of the UIScrollView view dynamically in the code on UITextView.textViewDidChange. I have a constraint for UIView.bottom that is equal to Superview.bottom (UIScrollView). Everything works until the UITextView view fits one screen.

How to adjust UIView programmatically to be equal to the UITextView size.

enter image description here


Solution

  • What you need to do is:

    • constrain the UITextView top / leading / trailing to its superview (the UIView)
    • constrain the UITextView bottom to its superview bottom (the UIView), with >=
    • constrain the UIView top / bottom / leading / trailing to its superview (the UIScrollView)
    • constrain the UIView width and height equal to width and height of its superview (the UIScrollView)
    • edit the height constraint and set Priority: 250

    This will allow the text view to grow / shrink vertically based on its content. The UIView will remain at the height of the scroll view, until the text view grows too tall to fit. At that point, the low Priority will allow the bottom edge of the UIView to be "pushed down" as the text view grows.

    Here's the layout in storyboard:

    enter image description here

    at runtime:

    enter image description here

    with lots of text and scrolled up:

    enter image description here

    And here's the source of the Storyboard (NO code needed - just the storyboard):

    <?xml version="1.0" encoding="UTF-8"?>
    <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="VM1-mg-1mG">
        <device id="retina4_7" orientation="portrait">
            <adaptation id="fullscreen"/>
        </device>
        <dependencies>
            <deployment identifier="iOS"/>
            <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
            <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="jpE-FH-8e8">
                <objects>
                    <viewController id="VM1-mg-1mG" sceneMemberID="viewController">
                        <view key="view" contentMode="scaleToFill" id="yS7-gh-XNz">
                            <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="gBx-Cd-lhB">
                                    <rect key="frame" x="8" y="120" width="359" height="447"/>
                                    <subviews>
                                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="UGW-Gc-H5B">
                                            <rect key="frame" x="0.0" y="0.0" width="359" height="447"/>
                                            <subviews>
                                                <textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" scrollEnabled="NO" text="This is the UITextView" textAlignment="natural" translatesAutoresizingMaskIntoConstraints="NO" id="wad-lw-VgC">
                                                    <rect key="frame" x="20" y="20" width="319" height="45"/>
                                                    <color key="backgroundColor" red="0.99942404029999998" green="0.98555368190000003" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                                    <fontDescription key="fontDescription" type="system" pointSize="24"/>
                                                    <textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
                                                </textView>
                                            </subviews>
                                            <color key="backgroundColor" red="0.52747867609999999" green="1" blue="0.55622484120000004" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                            <constraints>
                                                <constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="wad-lw-VgC" secondAttribute="bottom" constant="20" id="43l-VA-TfK"/>
                                                <constraint firstItem="wad-lw-VgC" firstAttribute="top" secondItem="UGW-Gc-H5B" secondAttribute="top" constant="20" id="6gx-L4-rfK"/>
                                                <constraint firstAttribute="trailing" secondItem="wad-lw-VgC" secondAttribute="trailing" constant="20" id="Hze-tT-ctt"/>
                                                <constraint firstItem="wad-lw-VgC" firstAttribute="leading" secondItem="UGW-Gc-H5B" secondAttribute="leading" constant="20" id="O7m-RX-NHL"/>
                                            </constraints>
                                        </view>
                                    </subviews>
                                    <color key="backgroundColor" red="0.46202266219999999" green="0.83828371759999998" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                    <constraints>
                                        <constraint firstItem="UGW-Gc-H5B" firstAttribute="top" secondItem="gBx-Cd-lhB" secondAttribute="top" id="9Ca-8i-QSo"/>
                                        <constraint firstAttribute="trailing" secondItem="UGW-Gc-H5B" secondAttribute="trailing" id="HpF-K7-pGb"/>
                                        <constraint firstItem="UGW-Gc-H5B" firstAttribute="width" secondItem="gBx-Cd-lhB" secondAttribute="width" id="T85-Nb-vFG"/>
                                        <constraint firstItem="UGW-Gc-H5B" firstAttribute="leading" secondItem="gBx-Cd-lhB" secondAttribute="leading" id="aKi-pE-7nq"/>
                                        <constraint firstItem="UGW-Gc-H5B" firstAttribute="height" secondItem="gBx-Cd-lhB" secondAttribute="height" priority="250" id="gMZ-MY-cZ4"/>
                                        <constraint firstAttribute="bottom" secondItem="UGW-Gc-H5B" secondAttribute="bottom" id="yBi-9n-Sd3"/>
                                    </constraints>
                                </scrollView>
                            </subviews>
                            <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                            <constraints>
                                <constraint firstItem="gBx-Cd-lhB" firstAttribute="top" secondItem="1Le-6E-02N" secondAttribute="top" constant="100" id="IpO-b2-zbv"/>
                                <constraint firstItem="1Le-6E-02N" firstAttribute="trailing" secondItem="gBx-Cd-lhB" secondAttribute="trailing" constant="8" id="XVi-7E-3hn"/>
                                <constraint firstItem="gBx-Cd-lhB" firstAttribute="leading" secondItem="1Le-6E-02N" secondAttribute="leading" constant="8" id="at7-bP-fws"/>
                                <constraint firstItem="1Le-6E-02N" firstAttribute="bottom" secondItem="gBx-Cd-lhB" secondAttribute="bottom" constant="100" id="nhL-ST-z4d"/>
                            </constraints>
                            <viewLayoutGuide key="safeArea" id="1Le-6E-02N"/>
                        </view>
                    </viewController>
                    <placeholder placeholderIdentifier="IBFirstResponder" id="6C7-lr-bGI" userLabel="First Responder" sceneMemberID="firstResponder"/>
                </objects>
                <point key="canvasLocation" x="136.80000000000001" y="124.58770614692655"/>
            </scene>
        </scenes>
    </document>