【问题标题】:How to make the entire page scrollable, when UITextView is inside UIScrollView?当 UITextView 在 UIScrollView 内时,如何使整个页面可滚动?
【发布时间】:2021-04-13 08:21:26
【问题描述】:

目前,我有如下布局设计

[Safe Area]

    [Scroll View (In green color)]
        
        [Custom View (In red color)]
            
            [Horizontal Stack View]
                [Button 1]
                [Button 2]
            
            [Text View]

    [Bottom Toolbar]

它被设计成,随着[Text View]的内容增长,用户可以垂直滚动[Text View]和按钮组([Horizontal Stack View]

应该是这样的

我们认为我们在[Custom View][Scroll View] 之间使用了正确的约束

Custom View.top = Content Layout Guide.top
Custom View.trailing = Content Layout Guide.trailing
Custom View.leading = Content Layout Guide.leading
Custom View.bottom = Content Layout Guide.bottom
Custom View.width = Frame Layout Guide.width

我们从 Xcode 得到的一个警告是

Scrollable content size is ambiguous for "Scroll View".

因此,为了避免这种情况,我们需要添加

Custom View.centerX = Frame Layout Guide.centerX
Custom View.centerY = Frame Layout Guide.centerY

但是,当我们执行应用程序时,只有[Text View] 是垂直可滚动的,当文本内容增长时。 顶部按钮组保持不变。

我们尝试禁用 [Text View] 本身的滚动行为。同样,当文本内容增长时,整个页面都不可滚动。

你知道如何解决这个问题,以便当文本内容增长时,顶部按钮组可以与文本视图一起滚动?

演示位于https://github.com/yccheok/ios-tutorial/tree/learn-scroll-view/NavigationController

【问题讨论】:

    标签: ios swift uiscrollview uitextview


    【解决方案1】:

    看来你很近了……

    UITextView 绝对应该禁用滚动。这将导致它随着用户键入而垂直增长/收缩。

    我认为,您缺少的关键点是文本视图的底部约束。

    这是它的布局方式 - 我为元素使用了 8 pt“填充”:

    这里是故事板的来源:

    <?xml version="1.0" encoding="UTF-8"?>
    <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="22Q-Va-uW9">
        <device id="retina6_1" orientation="portrait" appearance="light"/>
        <dependencies>
            <deployment identifier="iOS"/>
            <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
            <capability name="Safe area layout guides" minToolsVersion="9.0"/>
            <capability name="System colors in document resources" minToolsVersion="11.0"/>
            <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
        </dependencies>
        <scenes>
            <!--Text View Scroll View Controller-->
            <scene sceneID="cwD-Ry-Rln">
                <objects>
                    <viewController id="22Q-Va-uW9" customClass="TextViewScrollViewController" customModule="PanZoom" customModuleProvider="target" sceneMemberID="viewController">
                        <view key="view" contentMode="scaleToFill" id="FK3-2k-kFr">
                            <rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
                            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                            <subviews>
                                <scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="9i4-uC-ifa">
                                    <rect key="frame" x="0.0" y="88" width="414" height="725"/>
                                    <subviews>
                                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="cmb-lb-s1V" userLabel="GreenView">
                                            <rect key="frame" x="0.0" y="0.0" width="414" height="220.5"/>
                                            <subviews>
                                                <stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="dtt-fC-qBS" userLabel="ButtonsStack">
                                                    <rect key="frame" x="8" y="8" width="398" height="30"/>
                                                    <subviews>
                                                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="GFD-bo-TQG">
                                                            <rect key="frame" x="0.0" y="0.0" width="195" height="30"/>
                                                            <color key="backgroundColor" red="0.83741801979999997" green="0.83743780850000005" blue="0.83742713930000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                                            <state key="normal" title="Button 1"/>
                                                        </button>
                                                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="G0H-uo-Hhv">
                                                            <rect key="frame" x="203" y="0.0" width="195" height="30"/>
                                                            <color key="backgroundColor" red="0.83741801979999997" green="0.83743780850000005" blue="0.83742713930000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                                            <state key="normal" title="Button 2"/>
                                                        </button>
                                                    </subviews>
                                                </stackView>
                                                <textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" scrollEnabled="NO" textAlignment="natural" translatesAutoresizingMaskIntoConstraints="NO" id="31s-od-JSj">
                                                    <rect key="frame" x="8" y="46" width="398" height="166.5"/>
                                                    <color key="backgroundColor" systemColor="systemBackgroundColor"/>
                                                    <string key="text">Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda.</string>
                                                    <color key="textColor" systemColor="labelColor"/>
                                                    <fontDescription key="fontDescription" type="system" pointSize="14"/>
                                                    <textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
                                                </textView>
                                            </subviews>
                                            <color key="backgroundColor" red="0.97629755740000002" green="0.25518852469999997" blue="0.1867151558" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                            <constraints>
                                                <constraint firstAttribute="bottom" secondItem="31s-od-JSj" secondAttribute="bottom" constant="8" id="48L-4C-2qT"/>
                                                <constraint firstAttribute="trailing" secondItem="31s-od-JSj" secondAttribute="trailing" constant="8" id="8Fk-Hs-oE5"/>
                                                <constraint firstItem="31s-od-JSj" firstAttribute="top" secondItem="dtt-fC-qBS" secondAttribute="bottom" constant="8" id="FBX-A2-9r1"/>
                                                <constraint firstItem="dtt-fC-qBS" firstAttribute="top" secondItem="cmb-lb-s1V" secondAttribute="top" constant="8" id="ReQ-rG-pxE"/>
                                                <constraint firstAttribute="trailing" secondItem="dtt-fC-qBS" secondAttribute="trailing" constant="8" id="TNF-MC-1Fo"/>
                                                <constraint firstItem="dtt-fC-qBS" firstAttribute="leading" secondItem="cmb-lb-s1V" secondAttribute="leading" constant="8" id="cHU-IF-eqx"/>
                                                <constraint firstItem="31s-od-JSj" firstAttribute="leading" secondItem="cmb-lb-s1V" secondAttribute="leading" constant="8" id="vzb-fw-4rS"/>
                                            </constraints>
                                        </view>
                                    </subviews>
                                    <color key="backgroundColor" red="0.045027168950000002" green="0.85423937179999998" blue="0.076285673880000002" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
                                    <constraints>
                                        <constraint firstItem="cmb-lb-s1V" firstAttribute="trailing" secondItem="vj7-x9-CG7" secondAttribute="trailing" id="Ify-cz-Rri"/>
                                        <constraint firstItem="cmb-lb-s1V" firstAttribute="leading" secondItem="vj7-x9-CG7" secondAttribute="leading" id="Sup-Q0-buq"/>
                                        <constraint firstItem="cmb-lb-s1V" firstAttribute="top" secondItem="vj7-x9-CG7" secondAttribute="top" id="anR-gY-fDu"/>
                                        <constraint firstItem="cmb-lb-s1V" firstAttribute="width" secondItem="n5I-JV-9MK" secondAttribute="width" id="qXA-46-Ghy"/>
                                        <constraint firstItem="cmb-lb-s1V" firstAttribute="bottom" secondItem="vj7-x9-CG7" secondAttribute="bottom" id="xfn-l1-QHb"/>
                                    </constraints>
                                    <viewLayoutGuide key="contentLayoutGuide" id="vj7-x9-CG7"/>
                                    <viewLayoutGuide key="frameLayoutGuide" id="n5I-JV-9MK"/>
                                </scrollView>
                            </subviews>
                            <viewLayoutGuide key="safeArea" id="0PY-SX-dfw"/>
                            <color key="backgroundColor" systemColor="systemBackgroundColor"/>
                            <constraints>
                                <constraint firstItem="9i4-uC-ifa" firstAttribute="leading" secondItem="0PY-SX-dfw" secondAttribute="leading" id="VfX-uv-BcR"/>
                                <constraint firstItem="9i4-uC-ifa" firstAttribute="top" secondItem="0PY-SX-dfw" secondAttribute="top" id="nrt-pL-ZXy"/>
                                <constraint firstItem="9i4-uC-ifa" firstAttribute="bottom" secondItem="0PY-SX-dfw" secondAttribute="bottom" id="tLV-GX-hce"/>
                                <constraint firstItem="9i4-uC-ifa" firstAttribute="trailing" secondItem="0PY-SX-dfw" secondAttribute="trailing" id="v8d-TH-4oS"/>
                            </constraints>
                        </view>
                        <simulatedNavigationBarMetrics key="simulatedTopBarMetrics" prompted="NO"/>
                        <simulatedToolbarMetrics key="simulatedBottomBarMetrics"/>
                        <connections>
                            <outlet property="theScrollView" destination="9i4-uC-ifa" id="Wq7-j8-nud"/>
                        </connections>
                    </viewController>
                    <placeholder placeholderIdentifier="IBFirstResponder" id="QQ0-6m-9TV" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
                </objects>
                <point key="canvasLocation" x="331.8840579710145" y="162.72321428571428"/>
            </scene>
        </scenes>
        <resources>
            <systemColor name="labelColor">
                <color white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
            </systemColor>
            <systemColor name="systemBackgroundColor">
                <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
            </systemColor>
        </resources>
    </document>
    

    和一个带有键盘处理的示例视图控制器:

    class TextViewScrollViewController: UIViewController {
    
        @IBOutlet var theScrollView: UIScrollView!
        
        override func viewDidLoad() {
            super.viewDidLoad()
    
            // button to end editing
            let btn = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(self.doneTapped(_:)))
            self.navigationItem.rightBarButtonItem = btn
            
            let notificationCenter = NotificationCenter.default
            notificationCenter.addObserver(self, selector: #selector(adjustForKeyboard), name: UIResponder.keyboardWillHideNotification, object: nil)
            notificationCenter.addObserver(self, selector: #selector(adjustForKeyboard), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
    
        }
        
        @objc func doneTapped(_ sender: Any?) -> Void {
            view.endEditing(true)
        }
        
        @objc func adjustForKeyboard(notification: Notification) {
            guard let keyboardValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else { return }
            
            let keyboardScreenEndFrame = keyboardValue.cgRectValue
            let keyboardViewEndFrame = view.convert(keyboardScreenEndFrame, from: view.window)
            
            if notification.name == UIResponder.keyboardWillHideNotification {
                theScrollView.contentInset = .zero
            } else {
                // bottom padding to keep textView above keyboard - adjust as desired
                let padding: CGFloat = 16
                theScrollView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: keyboardViewEndFrame.height - (view.safeAreaInsets.bottom - padding), right: 0)
            }
            
            theScrollView.scrollIndicatorInsets = theScrollView.contentInset
            
        }
        
    }
    

    【讨论】:

      【解决方案2】:

      在滚动中滚动一直是一件棘手的事情。我的建议 -

      如果不可编辑,请勿使用UITextView,请使用UILabel

      计算文本的高度并使文本视图等于它并禁用滚动。这样你最终将只有一个可滚动的视图。 Helpful link.

      【讨论】:

      • 我们需要使用UITextView,因为这是一个笔记应用程序。
      • 然后使用第二种方法。自己控制文本视图的高度并禁用它的滚动。
      • 添加了有用的链接。
      猜你喜欢
      • 2019-03-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-12
      • 1970-01-01
      • 1970-01-01
      • 2011-08-23
      • 1970-01-01
      相关资源
      最近更新 更多