如何调整UIScrollView的大小以适应UILabel中未知数量的文本?

时间:2017-03-18 17:51:03

标签: ios swift uiscrollview uikit uiscrollviewdelegate

我在我的一个视图中添加了一个scrollview子视图,但是我很难达到它的高度以准确地适应scrollview显示的内容,这是UILabel中的文本。高度需要是动态的(即文本长度的一个因子),因为我正在为许多不同的文本长度实例化该视图。每当我记录label.frame.bounds时,我都会得到(0,0)。我在一些地方尝试sizeToFits()没有太多运气。

我的目标是让scrollview在到达最后一行文本时结束。另外,我只使用程序化约束。

我的代码的精简版本如下:

import UIKit

class ViewController: UIViewController, UIScrollViewDelegate {
    let scrollView = UIScrollView()
    let containerView = UIView()
    let label = UILabel()

    override func viewDidLoad() {
        super.viewDidLoad()

        scrollView.delegate = self

        // This needs to change
        scrollView.contentSize = CGSize(width: 375, height: 1000)

        scrollView.addSubview(containerView)
        view.addSubview(scrollView)

        label.text = unknownAmountOfText()
        label.backgroundColor = .gray


        containerView.isUserInteractionEnabled = true
        containerView.addSubview(label)

        label.translatesAutoresizingMaskIntoConstraints = false

        label.topAnchor.constraint(equalTo: containerView.topAnchor).isActive = true

        label.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        scrollView.frame = view.bounds
        containerView.frame = CGRect(x: 0, y: 0, width: scrollView.contentSize.width, height: scrollView.contentSize.height)
    }
}

感谢任何帮助。

找到解决方案:

func heightForLabel(text: String, font: UIFont, lineHeight: CGFloat, width: CGFloat) -> CGFloat {
    let label:UILabel = UILabel(frame: CGRect(x: 0, y: 0, width: width, height: CGFloat.greatestFiniteMagnitude))
    label.numberOfLines = 0
    label.lineBreakMode = NSLineBreakMode.byWordWrapping
    label.font = font
    label.text = text
    label.setLineHeight(lineHeight: lineHeight)
    label.sizeToFit()
    return label.frame.height
}

我在网上找到了这个解决方案,它根据标签的高度为我提供了为scrollView高度设置适当内容大小所需的内容。理想情况下,我可以在没有此功能的情况下确定这一点,但现在我很满意。

3 个答案:

答案 0 :(得分:2)

UIScrollView及其内容大小的关键是设置约束,以便实际的内容定义contentSize。

举一个简单的例子:假设你有一个宽度为200且高度为200的UIScrollView。现在你把UIView放在里面,宽度为100,高度为400.视图应该向上和向下滚动,但不能左右。您可以将视图限制为100x400,然后" pin"滚动视图两侧的顶部,底部,左侧和右侧,以及AutoLayout将自动神奇地"设置scrollview的contentSize。

当您添加可以更改大小的子视图时 - 显式(代码,用户交互)或隐式 - 如果正确设置了约束,那么这些更改也会#34 ;自动神奇"调整scrollview的contentSize。

所以......这是你要做的一个例子:

import UIKit

class ViewController: UIViewController, UIScrollViewDelegate {

    let scrollView = UIScrollView()
    let label = UILabel()

    let s1 = "1. This is the first line of text in the label. It has words and punctuation, but no embedded line-breaks, so what you see here is normal UILabel word-wrapping."
    var counter = 1

    override func viewDidLoad() {
        super.viewDidLoad()

        // turn off translatesAutoresizingMaskIntoConstraints, because we're going to set them
        scrollView.translatesAutoresizingMaskIntoConstraints = false
        label.translatesAutoresizingMaskIntoConstraints = false

        // set background colors, just so we can see the bounding boxes
        self.view.backgroundColor = UIColor(red: 1.0, green: 0.7, blue: 0.3, alpha: 1.0)
        scrollView.backgroundColor = UIColor(red: 0.8, green: 0.8, blue: 1.0, alpha: 1.0)
        label.backgroundColor = UIColor(white: 0.9, alpha: 1.0)

        // add the label to the scrollView, and the scrollView to the "main" view
        scrollView.addSubview(label)
        self.view.addSubview(scrollView)

        // set top, left, right constraints on scrollView to
        // "main" view + 8.0 padding on each side
        scrollView.topAnchor.constraint(equalTo: self.topLayoutGuide.bottomAnchor, constant: 8.0).isActive = true
        scrollView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 8.0).isActive = true
        scrollView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -8.0).isActive = true

        // set the height constraint on the scrollView to 0.5 * the main view height
        scrollView.heightAnchor.constraint(equalTo: self.view.heightAnchor, multiplier: 0.5).isActive = true

        // set top, left, right AND bottom constraints on label to
        // scrollView + 8.0 padding on each side
        label.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 8.0).isActive = true
        label.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 8.0).isActive = true
        label.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: -8.0).isActive = true
        label.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: -8.0).isActive = true

        // set the width of the label to the width of the scrollView (-16 for 8.0 padding on each side)
        label.widthAnchor.constraint(equalTo: scrollView.widthAnchor, constant: -16.0).isActive = true

        // configure label: Zero lines + Word Wrapping
        label.numberOfLines = 0
        label.lineBreakMode = NSLineBreakMode.byWordWrapping
        label.font = UIFont.systemFont(ofSize: 17.0)

        // set the text of the label
        label.text = s1

        // ok, we're done... but let's add a button to change the label text, so we
        // can "see the magic" happening
        let b = UIButton(type: UIButtonType.system)
        b.translatesAutoresizingMaskIntoConstraints = false
        self.view.addSubview(b)
        b.setTitle("Add a Line", for: .normal)
        b.topAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: 24.0).isActive = true
        b.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
        b.addTarget(self, action: #selector(self.btnTap(_:)), for: .touchUpInside)

    }

    func btnTap(_ sender: Any) {
        if let t = label.text {
            counter += 1
            label.text = t + "\n\n\(counter). Another line"
        }
    }

}

答案 1 :(得分:0)

使用containerView标记top,left,right和bottom约束。 和 set label.numberOfLines = 0 还要确保您已向containerView指定了top,left,right和bottom约束。这将解决您的问题

答案 2 :(得分:0)

从界面构建器设置自动布局约束,如image所示。 enter image description here

我将UIScrollView的高度设置为UIView的0.2

然后将UIlabel从MainStoryBoard拖动到视图控制器。

在viewdidload方法中添加这两行。

draggedlabel.numberOfLines = 0

draggedlabel.lineBreakMode = NSLineBreakMode.byWordWrapping