UILabel 내에서 텍스트를 세로로 정렬 (참고 : AutoLayout 사용)
나는 전에 질문 같은 질문 복사하고 질문 . 주어진 솔루션을 시도했지만 Autolayout 을 사용할 때 sizetofit 이 효과적이지 않았기 때문에 해결할 수 없었습니다.

예상되는 디스플레이는 다음과 같습니다.

편집하다
내 원래 대답에서는 레이블의 단락 스타일을 사용했습니다. 여러 줄 레이블의 경우 실제로 레이블이 여러 줄이되는 것을 방지합니다. 결과적으로 계산에서 제거했습니다. Github 에서 이에 대해 자세히 알아보십시오.
오픈 소스 사용에 더 익숙한 분들은 레이블의 텍스트 정렬을 다음과 같이 설정할 수 있는 TTTAttributedLabel 을 확인하십시오.TTTAttributedLabelVerticalAlignmentTop
트릭은 서브 클래스입니다 UILabel및 재정의 drawTextInRect. 그런 다음 텍스트가 레이블 경계의 원점에 그려 지도록합니다.
지금 바로 사용할 수있는 순진한 구현은 다음과 같습니다.
빠른
@IBDesignable class TopAlignedLabel: UILabel {
override func drawTextInRect(rect: CGRect) {
if let stringText = text {
let stringTextAsNSString = stringText as NSString
var labelStringSize = stringTextAsNSString.boundingRectWithSize(CGSizeMake(CGRectGetWidth(self.frame), CGFloat.max),
options: NSStringDrawingOptions.UsesLineFragmentOrigin,
attributes: [NSFontAttributeName: font],
context: nil).size
super.drawTextInRect(CGRectMake(0, 0, CGRectGetWidth(self.frame), ceil(labelStringSize.height)))
} else {
super.drawTextInRect(rect)
}
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
layer.borderWidth = 1
layer.borderColor = UIColor.blackColor().CGColor
}
}
스위프트 3
@IBDesignable class TopAlignedLabel: UILabel {
override func drawText(in rect: CGRect) {
if let stringText = text {
let stringTextAsNSString = stringText as NSString
let labelStringSize = stringTextAsNSString.boundingRect(with: CGSize(width: self.frame.width,height: CGFloat.greatestFiniteMagnitude),
options: NSStringDrawingOptions.usesLineFragmentOrigin,
attributes: [NSFontAttributeName: font],
context: nil).size
super.drawText(in: CGRect(x:0,y: 0,width: self.frame.width, height:ceil(labelStringSize.height)))
} else {
super.drawText(in: rect)
}
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
layer.borderWidth = 1
layer.borderColor = UIColor.black.cgColor
}
}
목표 -C
IB_DESIGNABLE
@interface TopAlignedLabel : UILabel
@end
@implementation TopAlignedLabel
- (void)drawTextInRect:(CGRect)rect {
if (self.text) {
CGSize labelStringSize = [self.text boundingRectWithSize:CGSizeMake(CGRectGetWidth(self.frame), CGFLOAT_MAX)
options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
attributes:@{NSFontAttributeName:self.font}
context:nil].size;
[super drawTextInRect:CGRectMake(0, 0, ceilf(CGRectGetWidth(self.frame)),ceilf(labelStringSize.height))];
} else {
[super drawTextInRect:rect];
}
}
- (void)prepareForInterfaceBuilder {
[super prepareForInterfaceBuilder];
self.layer.borderWidth = 1;
self.layer.borderColor = [UIColor blackColor].CGColor;
}
@end
IBDesignable을 사용했기 때문에이 레이블을 스토리 보드에 추가하고 진행되는 것을 볼 수 있습니다.

UILabel이 고정 된 크기로 제한되지 않는 경우 UILabel 내에서 텍스트를 정렬하는 대신 지정된 레이블에 ≥ 제약 조건을 사용하여 크기를 변경하면됩니다.
자동 레이아웃을 사용하는 가장 우아한 솔루션입니다. 그래도 numberOfLines 를 0 으로 설정하는 것을 잊지 마십시오 .
UILabel 대신 UITextView를 사용할 수 있습니다.
"스크롤 사용"
선택 취소 "편집 가능" 선택
취소 "선택 가능"선택 취소
배경색을 ClearColor로 설정
나는 같은 문제가 있었고 이것이 내가 그것을 해결 한 방법입니다. 레이블에 대한 속성 검사기에서 기준선을 편집했습니다. "Align Centers"로 설정합니다.
대신 Bottom Space Constant를 우선 순위 @ 250으로 변경하고 문제를 해결했습니다. 그리고 내 레이블에는 <= 상수로 높이 상수가 있습니다.
최소 높이를 제거하면됩니다.
레이블 아래의 다른 높이에 최소 높이가 필요한 경우 레이블 내용에 따라 크기가 조정되었지만 최소값을 사용하는 컨테이너보기를 사용합니다.
자동 레이아웃은 컨트롤러 콘텐츠가 아닌 컨트롤러의 가장자리 / 크기에서만 작동하므로 자동 레이아웃을 사용하여 레이블 텍스트를 첫 줄에 표시하는 것은 좋지 않습니다. 나에 따르면 sizetofit은 최선의 선택입니다.
@Daniel Golasko의 솔루션을 사용했으며 UILabel 내부의 텍스트가 UILabel이 포함 할 수있는 것보다 길 때마다 텍스트가 맨 위에 정렬되는 대신 아래로 이동하기 시작했습니다.
텍스트가 제대로 정렬되도록이 줄을 변경했습니다.
[super drawTextInRect:CGRectMake(0, 0, ceilf(CGRectGetWidth(self.frame)),MIN(ceilf(labelStringSize.height), self.frame.size.height))];
3 개의 레이블이있는 비슷한 문제가있었습니다. 중간 레이블은 다른 두 레이블보다 훨씬 긴 텍스트를 가질 수 있으므로 높이가 훨씬 더 커질 수 있습니다.
이렇게 :
중간 레이블의 아래쪽 공간 제약 조건을> = 아래쪽 레이블로 설정했습니다.
그것은 내 문제를 해결했습니다.
이 라벨의 높이가 일정 할 필요가없는 경우에 대한 쉬운 솔루션입니다 : 당신을 넣어 LabelA의 Stack View. 에 선행 및 후행 상수를 추가해야합니다 Stack View. 다음은 스토리 보드에서 수행하는 방법의 스크린 샷입니다.
스위프트 4
UILabel을 하위 클래스로 만들고 텍스트 디스플레이 렌더링을 재정의해야합니다.
class UITopAlignedLabel: UILabel {
override func drawText(in rect: CGRect) {
guard let string = text else {
super.drawText(in: rect)
return
}
let size = (string as NSString).boundingRect(
with: CGSize(width: rect.width, height: .greatestFiniteMagnitude),
options: [.usesLineFragmentOrigin],
attributes: [.font: font],
context: nil).size
var rect = rect
rect.size.height = size.height.rounded()
super.drawText(in: rect)
}
}
당신은 버튼을 시도 할 수 있습니다 [button setContentVerticalAlignment:UIControlContentVerticalAlignmentTop];
편집하다 :
레이블 만 사용하려는 경우 이것을 시도 할 수 있습니다.
https://stackoverflow.com/a/11278660/1223897
나를 위해 높이 제한을 설정하지 않았으며 텍스트는 항상 레이블 상단에서 커집니다. 이 레이블의 제약 조건은 위쪽, 왼쪽, 오른쪽입니다. 덧붙여서 내 라벨에는 고정 된 줄 번호가 있으므로 높이에 대해 걱정할 필요가 없습니다.
@IBInspectable var alignTop: Bool = false
func setAlignTop() {
let text = self.text!
let lines = text.characters.split(separator: "\n").count
if lines < self.numberOfLines {
var newLines = ""
for _ in 0..<(self.numberOfLines - lines) {
newLines = newLines.appending("\n ")
}
self.text! = text.appending(newLines)
}
}
override var text: String? {
didSet {
if alignTop {
self.setAlignTop()
}
}
}
다음은 Daniel Galasko의 Swift 3 솔루션에 대한 개선 사항입니다 (여기서는 상단에 오프셋없이 최대 줄 수를 설정할 수도 있습니다).
import UIKit
@IBDesignable class TopAlignedLabel: UILabel {
override func drawText(in rect: CGRect) {
if let stringText = text {
let stringTextAsNSString = stringText as NSString
let labelString = stringTextAsNSString.boundingRect(with: CGSize(width: frame.width, height: .greatestFiniteMagnitude),
options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)
super.drawText(in: CGRect(x: 0, y: 0, width: frame.width, height: ceil(labelString.size.height) > frame.height ? frame.height : ceil(labelString.size.height)))
} else {
super.drawText(in: rect)
}
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
layer.borderWidth = 1
layer.borderColor = UIColor.black.cgColor
}
}
이 내 수업을 사용 하면 텍스트 alignment를 contentMode.
지원되는 케이스 : .top, .bottom, .left, .right, .topLeft, .topRight, .bottomLeft, .bottomRight
Swift4
import Foundation
import UIKit
@IBDesignable
class UIAlignedLabel: UILabel {
override func drawText(in rect: CGRect) {
if let text = text as NSString? {
func defaultRect(for maxSize: CGSize) -> CGRect {
let size = text
.boundingRect(
with: maxSize,
options: NSStringDrawingOptions.usesLineFragmentOrigin,
attributes: [
NSAttributedStringKey.font: font
],
context: nil
).size
let rect = CGRect(
origin: .zero,
size: CGSize(
width: min(frame.width, ceil(size.width)),
height: min(frame.height, ceil(size.height))
)
)
return rect
}
switch contentMode {
case .top, .bottom, .left, .right, .topLeft, .topRight, .bottomLeft, .bottomRight:
let maxSize = CGSize(width: frame.width, height: frame.height)
var rect = defaultRect(for: maxSize)
switch contentMode {
case .bottom, .bottomLeft, .bottomRight:
rect.origin.y = frame.height - rect.height
default: break
}
switch contentMode {
case .right, .topRight, .bottomRight:
rect.origin.x = frame.width - rect.width
default: break
}
super.drawText(in: rect)
default:
super.drawText(in: rect)
}
} else {
super.drawText(in: rect)
}
}
}
'Program Club' 카테고리의 다른 글
| 같은 뷰에서 setFrame과 autolayout을 사용할 수 있습니까? (0) | 2020.11.25 |
|---|---|
| Visual Studio에서 모든 탭 닫기 (0) | 2020.11.25 |
| Core Data 다중 스레드 애플리케이션 (0) | 2020.11.25 |
| 치명적인 오류 : 정의되지 않은 함수 mcrypt_encrypt () 호출 (0) | 2020.11.25 |
| CamelCase 단어를 PHP preg_match (정규식)를 사용하여 단어로 분할 (0) | 2020.11.25 |




