ios - 根据内容调整 uiscrollview 的大小

标签 ios swift uiscrollview pure-layout

当内容添加到我的标签时,我在调整大小和使 ScrollView 可垂直滚动时遇到一些问题。我的层次结构如下所示:

my hierarchy

虽然我的观点是这样的:

my view

因此,当我从 API 调用中获取文本时,我想在开始时用代码中的内容填写标签。但出于测试目的,我刚刚硬编码了一些 lorem ipsum 文本以使其工作。因此,我的内容被添加到标签中,并且 UILabels 调整大小,并且包含标签调整大小的 View 也被添加。我在调整 ScrollView 内容大小时遇到​​问题,以便在标签中的文本较长时可以滚动。这也是我当前的代码:

import UIKit
import PureLayout

class QuestionAndAnswerViewController: UIViewController {

@IBOutlet var menuButton: UIBarButtonItem!
@IBOutlet var questionView: UIView!
@IBOutlet var questionLabel: UILabel!
@IBOutlet var questionContentLabel: UILabel!
@IBOutlet var answerView: UIView!

@IBOutlet var odgovorLabel: UILabel!
@IBOutlet var answerLabel: UILabel!
@IBOutlet var signLabel: UILabel!

@IBOutlet var lineView: UIView!

@IBOutlet var scrollView: UIScrollView!
@IBOutlet var contentView: UIView!

var yPosition: CGFloat = 0.0
var contentSize: CGFloat = 0.0
var attrText = NSMutableAttributedString()

override func viewDidLoad() {
    super.viewDidLoad()

    scrollView.setNeedsLayout()
    scrollView.layoutIfNeeded()
    scrollView.translatesAutoresizingMaskIntoConstraints = false


    let paragraphStyle = NSMutableParagraphStyle()
    paragraphStyle.lineSpacing = 5
    paragraphStyle.alignment = .justified

    let paragraphStyle2 = NSMutableParagraphStyle()
    paragraphStyle2.lineSpacing = 5
    paragraphStyle2.alignment = .left


    if self.revealViewController() != nil {
        self.revealViewController().frontViewShadowRadius = 5.0
        self.revealViewController().frontViewShadowOpacity = 0.25
        menuButton.target = self.revealViewController()
        menuButton.action = #selector(SWRevealViewController.rightRevealToggle(_:))
        self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
    }

    var text = "To je prvo vprašanje? Kako dolgi je lahko ta tekst da se poravna"
    attrText = NSMutableAttributedString(string: text)
    attrText.addAttribute(NSParagraphStyleAttributeName, value: paragraphStyle2, range: NSMakeRange(0, attrText.length))
    questionLabel.attributedText = attrText


    text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut quis mi nisi. Etiam nec augue id dui blandit ornare. Nulla auctor, purus vel tincidunt ultricies, enim turpis molestie augue, nec mattis libero ante mattis mauris. Suspendisse posuere, velit posuere viverra feugiat, nulla justo bibendum nisi, nec ultricies lorem enim in nisl. Nunc sit amet quam mollis, faucibus felis eu, posuere dui. Sed vel mattis neque. Fusce elementum at nisl ut volutpat. Nam placerat consequat mi in lacinia. Morbi ut est tristique, efficitur est a, faucibus erat. Suspendisse et ligula ac lacus porttitor pretium ut vehicula felis."
    attrText = NSMutableAttributedString(string: text)

    attrText.addAttribute(NSParagraphStyleAttributeName, value: paragraphStyle, range: NSMakeRange(0, attrText.length))
    questionContentLabel.attributedText = attrText


    text = "Cras auctor ullamcorper ullamcorper. Vestibulum dignissim quis risus eget congue. Sed et diam libero. Phasellus non lectus sem. Cras auctor ullamcorper ullamcorper. Vestibulum dignissim quis risus eget congue. Sed et diam libero. Phasellus non lectus sem. Cras auctor ullamcorper ullamcorper. Vestibulum dignissim quis risus eget congue. Sed et diam libero. Phasellus non lectus sem. Cras auctor ullamcorper ullamcorper. Vestibulum dignissim quis risus eget congue. Sed et diam libero. Phasellus non lectus sem."
    attrText = NSMutableAttributedString(string: text)
    attrText.addAttribute(NSParagraphStyleAttributeName, value: paragraphStyle, range: NSMakeRange(0, attrText.length))
    answerLabel.attributedText = attrText

    setupConstraints()

    contentView.frame = CGRect(x: contentView.frame.origin.x, y: contentView.frame.origin.y, width: contentView.frame.width, height: 2000)
    scrollView.contentSize = CGSize(width: contentView.frame.width, height: 2000)

    print(scrollView.contentSize)
}


func setupConstraints() {


    //Question Contstraints
    questionView.autoPinEdge(.top, to: .top, of: contentView, withOffset: 30)
    questionView.autoPinEdge(.left, to: .left, of: contentView, withOffset: 0)
    questionView.autoPinEdge(.right, to: .right, of: contentView, withOffset: 0)

    questionView.autoPinEdge(.top, to: .top, of: questionLabel, withOffset: -10)
    questionLabel.autoPinEdge(.right, to: .right, of: questionView, withOffset: -20)
    questionLabel.autoPinEdge(.left, to: .left, of: questionView, withOffset: 20)

    lineView.autoPinEdge(.top, to: .bottom, of: questionLabel, withOffset: 20)
    lineView.autoPinEdge(.left, to: .left, of: questionView, withOffset: 20)
    lineView.autoPinEdge(.right, to: .right, of: questionView, withOffset: -20)
    lineView.autoSetDimensions(to: CGSize(width: lineView.frame.width, height: 2))

    questionContentLabel.autoPinEdge(.top, to: .bottom, of: lineView, withOffset: 20)
    questionContentLabel.autoPinEdge(.right, to: .right, of: questionView, withOffset: -20)
    questionContentLabel.autoPinEdge(.left, to: .left, of: questionView, withOffset: 20)
    questionView.autoPinEdge(.bottom, to: .bottom, of: questionContentLabel, withOffset: 20)


    //Anwser Constraints
    answerView.autoPinEdge(.top, to: .bottom, of: questionView, withOffset: 10)
    answerView.autoPinEdge(.left, to: .left, of: contentView, withOffset: 0)
    answerView.autoPinEdge(.right, to: .right, of: contentView, withOffset: 0)


    odgovorLabel.autoPinEdge(.top, to: .top, of: answerView, withOffset: 10)
    odgovorLabel.autoPinEdge(.left, to: .left, of: answerView, withOffset: 20)
    odgovorLabel.autoPinEdge(.right, to: .right, of: answerView, withOffset: -20)

    answerLabel.autoPinEdge(.top, to: .bottom, of: odgovorLabel, withOffset: 20)
    answerLabel.autoPinEdge(.left, to: .left, of: answerView, withOffset: 20)
    answerLabel.autoPinEdge(.right, to: .right, of: answerView, withOffset: -20)

    signLabel.autoPinEdge(.top, to: .bottom, of: answerLabel, withOffset: 20)
    signLabel.autoPinEdge(.left, to: .left, of: answerView, withOffset: 20)
    signLabel.autoPinEdge(.right, to: .right, of: answerView, withOffset: -20)

    contentView.autoPinEdge(.bottom, to: .bottom, of: answerView)

    //answerView.autoPinEdge(.bottom, to: .bottom, of: signLabel, withOffset: 20)

}


override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

@IBAction func backButtonPressed(_ sender: Any) {
    navigationController?.popViewController(animated: true)
}
}

我还使用 PureLayout,因为这是我能够根据文本长度制作标签和 View 调整大小的唯一方法。

最佳答案

我不确定你在 Storyboard中为 scrollViewcontentView 设置了哪些约束,我必须说我有点好奇为什么使用 set直接在 viewDidLayout 中为其设置框架:

contentView.frame = CGRect(x: contentView.frame.origin.x, y: contentView.frame.origin.y, width: contentView.frame.width, height: 2000)
scrollView.contentSize = CGSize(width: contentView.frame.width, height: 2000)

您希望自动计算,对吗?

当我需要可 ScrollView 时我该怎么做:

  1. 我将一个 scrollView 添加到层次结构中,并使用自动布局来正确布局它,例如,如果它应该覆盖 的整个 view >viewController:

    scrollView.translatesAutoresizingMaskIntoConstraints = false
    
    scrollView.leftAnchor.constraint(equalTo: self.view.leftAnchor).isActive = true
    scrollView.rightAnchor.constraint(equalTo: self.view.rightAnchor).isActive = true
    scrollView.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
    scrollView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true
    
  2. 然后我需要向 scrollView 添加一个 contentView 并为其提供适当的布局约束,所以如果我想要垂直滚动 scrollView 在我上面开始的示例中,我需要以下自动布局约束:

    contentView.translatesAutoresizingMaskIntoConstraints = false
    
    contentView.leftAnchor.constraint(equalTo: self.view.leftAnchor).isActive = true
    contentView.rightAnchor.constraint(equalTo: self.view.rightAnchor).isActive = true
    contentView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
    contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
    

    请注意,我将 contentViewleftAnchorrightAnchor 约束到 self.view 而不是到 scrollView 使其具有固定宽度。但是,顶部和底部 anchor 受到 ScrollView 的限制,因此当 contentView 需要更多空间时,它们会展开并可滚动。

  3. 现在,我将所需的所有内容添加到 contentView 中,并使用自动布局对其进行布局,就好像 contentView 是一个具有无限高度的 View - scrollView 将负责通过滚动来呈现整个内容。因此,在我的示例中,如果唯一的内容是一个包含许多行的巨大 UILabel:

    label.translatesAutoresizingMaskIntoConstraints = false
    
    label.leftAnchor.constraint(equalTo: contentView.leftAnchor).isActive = true
    label.rightAnchor.constraint(equalTo: contentView.rightAnchor).isActive = true
    label.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
    label.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
    

尝试检查您的代码并检查您的约束(我使用自动布局编写了约束,但我想您应该能够轻松地将它们转换为 PureLayout 和 Storyboard)。

关于ios - 根据内容调整 uiscrollview 的大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46220546/

相关文章:

iphone - UIScrollView 在模拟器中过来 UIImage

ios - UIAlertController 中的自定义 View

android - Firebase IOS UTM 安装跟踪

ios - Alamofire - 具有多个证书的 IOS SSL Pinning

ios - 在表格被向下拖动之前在 UITableView 中显示滚动条。在某种程度上,UIScrollBar 应该始终可见

ios - NSPredicate 根据嵌套结构中的属性过滤自定义对象

swift - 如何将.ply、.STL、.dae文件转换为苹果SceneKit框架支持的.scn文件格式?

ios - Swift 4 局部变量赋值

ios - 即使 UIView 框架增加,UIScrollview 也不会滚动超出 UIView 高度

ios - AutoLayout UIScrollView 内容在旋转时不调整大小(包括示例项目)