2017-03-18 14 views
0

내보기 중 하나에서 scrollview 하위보기를 추가했지만 UILabel의 텍스트 인 scrollview의 내용에 정확히 맞게 높이를 얻는 데 문제가 있습니다. 텍스트 길이가 여러 개인 경우이보기를 인스턴스화 할 때 높이가 동적이어야합니다 (예 : 텍스트 길이의 요소). 내가 로그 할 때마다 label.frame.bounds (0,0)이 나옵니다. 나는 또한 운이 좋지 않은 몇 군데에서 sizeToFits()을 시도했다.UILabel에서 알 수없는 양의 텍스트에 맞게 UIScrollView의 크기를 조정하는 방법은 무엇입니까?

제 목표는 스크롤 막대가 텍스트의 마지막 줄에 도달하면 끝내도록하는 것입니다. 또한 프로그래밍 방식 제약 만 사용하고 있습니다.

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 높이에 해당하는 내용의 크기를 설정하는 데 필요한 걸 제공하는 온라인이 솔루션을 발견했다. 이상적으로, 나는이 기능없이 이것을 결정할 수있을 것이지만, 지금은 만족한다.

+0

왜 당신이 인터페이스 빌더보다 프로그래밍 오히려이 일을하고 있습니다 :

그래서 ... 여기 당신이 뭘 하려는지의 예입니다? 이것을 처리하는 가장 쉬운 방법은 레이아웃 제약 조건을 사용하는 것입니다.하지만 코드에서 매우 빨리 추악해질 수 있습니다. –

+0

왜 UILabel을 UIScrollView에 넣은 다음 레이블에 맞게 스크롤보기의 크기를 조정하려고합니까? 스크롤링 하시겠습니까? 그렇다면 스크롤보기의 크기를 조정하는 이유는 무엇입니까? 스크롤을 원하지 않는다면, 왜 스크롤 뷰에 레이블을 넣으시겠습니까? – DonMag

+0

프로그래밍 방식 레이아웃으로 만 프로젝트를 시도하고 싶었습니다. 내 다음 프로젝트에서는 인터페이스 빌더를 사용할 것이라고 생각합니다. 그러나 지금은 전환하기에 너무 깊이 생각하고 있습니다. 그래서 이것을 프로그램 적으로 파악해야합니다. –

답변

1

UIScrollView의 키와 내용 크기는 실제 콘텐츠이 contentSize를 정의하도록 제약 조건을 설정합니다.

간단한 예를 들어, 너비가 200이고 높이가 200 인 UIScrollView가 있다고 가정 해 보겠습니다. 이제 width : 100 및 height : 400 인 UIView를 배치합니다. 뷰는 위아래로 스크롤해야하지만 좌우가 아닙니다. 뷰를 100x400으로 제한 한 다음 스크롤 뷰의 측면에 위, 아래, 왼쪽 및 오른쪽을 "고정"할 수 있으며 AutoLayout은 scrollview의 contentSize를 "자동으로"자동 설정합니다. 하나 명시 적으로 (코드, 사용자 상호 작용) 또는 암시 적으로을 - - 제약이 올바르게 설정되어있는 경우 해당 변경 사항은 또한 "자동 마술"는있는 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" 
     } 
    } 

} 
+0

스크롤 사용의 적절한 사용과 마술을 완전히 조명 해 주셔서 감사합니다. 이 예제는 완벽했습니다 –

+0

또 하나의 질문은 ... 당신은 이미 그것의 선행 및 후행 앵커를 설정했기 때문에 레이블에'widthAnchor'를 설정해야합니까? –

+0

예 ... 선행, 후행, 위쪽 및 아래쪽 앵커가 scrollView에 "이 내용이 contentSize의 가장자리"임을 알립니다 ... 너비 앵커가 "이보다 더 넓어지게하지 마십시오"라고 말합니다 ... 아니요 높이 앵커입니다. 왜냐하면 텍스트에 맞게 레이블을 늘려야하기 때문입니다. – DonMag

0

containerView로 레이블에 top, left, right 및 bottom 제약 조건을 부여합니다. 및 set label.numberOfLines = 0 또한 containerView에 위쪽, 왼쪽, 오른쪽 및 아래쪽 제약 조건을 지정했는지 확인하십시오. 이 문제를 해결할 것입니다