垂直ScrollView不滚动(无情节提要)

时间:2020-08-01 21:01:26

标签: ios swift uiscrollview

我需要创建没有情节提要的滚动视图的帮助。这是我设置滚动视图的代码;我没有设置Scroll View的contentSize,因为我希望滚动视图的内容大小是动态的,具体取决于TextView中的文本量。我所做的是,尝试将“ contentView”添加到“滚动视图”并将所有UI元素添加到contentView中。任何帮助将不胜感激。

import Foundation
import UIKit
import UITextView_Placeholder

class ComposerVC: UIViewController {
  
  private var scrollView: UIScrollView = {
    let scrollView = UIScrollView(frame: UIScreen.main.bounds)
    scrollView.translatesAutoresizingMaskIntoConstraints = false
    return scrollView
  }()
  
  private var contentView: UIView = {
    let content = UIView()
    content.translatesAutoresizingMaskIntoConstraints = false
    return content
  }()
  
  private var title: UITextView = {
    let title = UITextView()
    title.translatesAutoresizingMaskIntoConstraints = false
    title.placeholder = "Untitled"
    title.textColor = UIColor(hexString: "#50E3C2")
    title.font = UIFont(name: "Rubik-BoldItalic", size: 32)
    title.backgroundColor = .clear
    title.isScrollEnabled = false
    return title
  }()
  
  private var divider: UIView = {
    let divider = UIView()
    divider.translatesAutoresizingMaskIntoConstraints = false
    divider.backgroundColor = UIColor(hexString: "#50E3C2")
    return divider
  }()
  
  private var content: UITextView = {
    let title = UITextView()
    title.translatesAutoresizingMaskIntoConstraints = false
    title.placeholder = "Begin writing here..."
    title.textColor = .white
    title.font = UIFont(name: "Avenir-Book", size: 15)
    title.backgroundColor = .clear
    title.isScrollEnabled = false
    return title
  }()
  
  override func viewDidLoad() {
    setupUI()
    setupUIConstraints()
    title.delegate = self
  }
  
  private func setupUI() {
    view.backgroundColor = UIColor(hexString: "#131415")
    view.addSubview(scrollView)
    scrollView.addSubview(contentView)
    contentView.addSubview(title)
    contentView.addSubview(divider)
    contentView.addSubview(content)
  }
  
  private func setupUIConstraints() {
    
    scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
    scrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
    scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
    scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
    
    contentView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
    contentView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
    contentView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
    contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
    contentView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
    
    title.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 95).isActive = true
    title.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 35).isActive = true
    title.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -35).isActive = true
    
    divider.topAnchor.constraint(equalTo: title.bottomAnchor, constant: 15).isActive = true
    divider.centerXAnchor.constraint(equalTo: contentView.centerXAnchor).isActive = true
    divider.heightAnchor.constraint(equalToConstant: 1).isActive = true
    divider.widthAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: 0.8).isActive = true
    
    content.topAnchor.constraint(equalTo: divider.bottomAnchor, constant: 15).isActive = true
    content.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 35).isActive = true
    content.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -35).isActive = true
  }
}

extension ComposerVC: UITextViewDelegate {
  func textViewDidChange(_ textView: UITextView) {
    let fixedWidth = textView.frame.size.width
    let newSize = textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
    textView.frame.size = CGSize(width: max(newSize.width, fixedWidth), height: newSize.height)
  }
}

2 个答案:

答案 0 :(得分:1)

一些提示:

  1. 不要使用现有的变量名...按原样使用代码,private var title: UITextView会导致问题(title已经是视图控制器属性)。
  2. 使用暗示对象的var名称...例如titleTextViewcontentTextView代替titlecontent
  3. 在开发过程中-特别是在布局时-为UI元素提供对比的背景色,以便您可以在运行时轻松查看其框架。
  4. 使用代码创建的视图时,设置.clipsToBounds = true ...如果看不到已添加的任何子视图,则说明框架/约束缺少某些内容。

我没有您的UITextView_Placeholder导入,但这对这里没有任何影响...

因此,首先,将您的viewDidLoad()更改为此:

override func viewDidLoad() {
    setupUI()
    setupUIConstraints()
    titleTextView.delegate = self
    
    // contrasting colors during development
    scrollView.backgroundColor = .red
    titleTextView.backgroundColor = .yellow
    contentTextView.backgroundColor = .green
    divider.backgroundColor = .blue
    contentView.backgroundColor = .cyan
}

运行它时,您应该看到(滚动视图背景为红色,并且没有占位符):

enter image description here

除了没有青色的contentView以外,它看起来 正确。

现在,剪辑contentView的子视图:

private var contentView: UIView = {
    let content = UIView()
    content.translatesAutoresizingMaskIntoConstraints = false
    // add this line
    content.clipsToBounds = true
    return content
}()

结果:

enter image description here

一切都去哪儿了?好吧,我们 没有 看到青色的contentView,现在我们看不到其 子视图 < / em> ...如果我们使用Debug View Hierarchy,我们会发现contentView的高度为零。

通过约束setupUIConstraints()中第二个文本视图的底部来解决此问题(我已将其重命名为contentTextView而不是仅仅content):

    contentTextView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -95).isActive = true

我们得到:

enter image description here

现在,通过正确设置其子视图的约束来控制青色contentView的高度。

作为旁注:正确设置了约束,并且在文本视图中禁用了滚动,因此您不需要:

extension ComposerVC: UITextViewDelegate {
  //func textViewDidChange(_ textView: UITextView) {
  //...
  //}
}

文本视图将自动将其大小调整为文本:

enter image description here

这是完整的编辑代码:

class ComposerVC: UIViewController {
    
    private var scrollView: UIScrollView = {
        let scrollView = UIScrollView(frame: UIScreen.main.bounds)
        scrollView.translatesAutoresizingMaskIntoConstraints = false
        return scrollView
    }()
    
    private var contentView: UIView = {
        let content = UIView()
        content.translatesAutoresizingMaskIntoConstraints = false
        // add this line so we know if the constraints are set correctly
        content.clipsToBounds = true
        return content
    }()
    
    private var titleTextView: UITextView = {
        let title = UITextView()
        title.translatesAutoresizingMaskIntoConstraints = false
//      title.placeholder = "Untitled"
        title.textColor = UIColor(hexString: "#50E3C2")
        title.font = UIFont(name: "Rubik-BoldItalic", size: 32)
        title.backgroundColor = .clear
        title.isScrollEnabled = false
        return title
    }()
    
    private var divider: UIView = {
        let divider = UIView()
        divider.translatesAutoresizingMaskIntoConstraints = false
        divider.backgroundColor = UIColor(hexString: "#50E3C2")
        return divider
    }()
    
    private var contentTextView: UITextView = {
        let title = UITextView()
        title.translatesAutoresizingMaskIntoConstraints = false
//      title.placeholder = "Begin writing here..."
        title.textColor = .white
        title.font = UIFont(name: "Avenir-Book", size: 15)
        title.backgroundColor = .clear
        title.isScrollEnabled = false
        return title
    }()
    
    override func viewDidLoad() {
        setupUI()
        setupUIConstraints()
        titleTextView.delegate = self
        
        // contrasting colors during development
        scrollView.backgroundColor = .red
        titleTextView.backgroundColor = .yellow
        contentTextView.backgroundColor = .green
        divider.backgroundColor = .blue
        contentView.backgroundColor = .cyan
    }
    
    private func setupUI() {
        view.backgroundColor = UIColor(hexString: "#131415")
        view.addSubview(scrollView)
        scrollView.addSubview(contentView)
        contentView.addSubview(titleTextView)
        contentView.addSubview(divider)
        contentView.addSubview(contentTextView)
    }
    
    private func setupUIConstraints() {
        
        scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        scrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
        scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
        
        contentView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
        contentView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
        contentView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
        contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
        contentView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
        
        titleTextView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 95).isActive = true
        titleTextView.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 35).isActive = true
        titleTextView.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -35).isActive = true
        
        divider.topAnchor.constraint(equalTo: titleTextView.bottomAnchor, constant: 15).isActive = true
        divider.centerXAnchor.constraint(equalTo: contentView.centerXAnchor).isActive = true
        divider.heightAnchor.constraint(equalToConstant: 1).isActive = true
        divider.widthAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: 0.8).isActive = true
        
        contentTextView.topAnchor.constraint(equalTo: divider.bottomAnchor, constant: 15).isActive = true
        contentTextView.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 35).isActive = true
        contentTextView.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -35).isActive = true
        
        contentTextView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -95).isActive = true
    
    }
}

extension ComposerVC: UITextViewDelegate {
//  func textViewDidChange(_ textView: UITextView) {
//      let fixedWidth = textView.frame.size.width
//      let newSize = textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
//      textView.frame.size = CGSize(width: max(newSize.width, fixedWidth), height: newSize.height)
//  }
}

答案 1 :(得分:0)

假设您使用的是iOS 11+,则contentView的锚点应限制在scrollView的contentLayoutGuide上。像这样:

contentView
    .leadingAnchor
    .constraint(equalTo: scrollView.contentLayoutGuide.leadingAnchor).isActive = true
contentView
    .topAnchor
    .constraint(equalTo: scrollView.contentLayoutGuide.topAnchor).isActive = true
contentView
    .trailingAnchor
    .constraint(equalTo: scrollView.contentLayoutGuide.trailingAnchor).isActive = true
contentView
    .bottomAnchor
    .constraint(equalTo: scrollView.contentLayoutGuide.bottomAnchor).isActive = true

此外,它的宽度应该限制在scrollView的frameLayoutGuide上,而不是视图的宽度上,如下所示:

contentView
.widthAnchor
.constraint(equalTo: scrollView.frameLayoutGuide.widthAnchor).isActive = true

这应该使scrollView检测到适合的内容大小。