내 펜촉 파일에 레이블 하나를 추가 한 다음 해당 레이블에 대해 왼쪽 상단 정렬이 필요합니다. 런타임에 텍스트를 제공하므로 얼마나 많은 줄이 있는지 확실하지 않습니다. 따라서 텍스트에 한 줄만 포함되어 있으면 세로 중앙 정렬로 나타납니다. 그 정렬은 그 앞에있는 내 각 레이블과 일치하지 않습니다.
예를 들면 :
이상하게 보입니다 🙁
레이블 텍스트를 왼쪽 위 정렬에 맞게 설정할 수있는 방법이 있습니까?
답변
다시 설명하기보다는 다소 광범위하고 높은 등급의 질문 / 답변을 링크하겠습니다.
짧은 대답은 아니오입니다. Apple은 이것을 쉽게 만들지 않았지만 프레임 크기를 변경하면 가능합니다.
답변
매우 쉽습니다. 크리에이트 UILabel
A를 sublcass verticalAlignment
속성을 재정의 textRectForBounds:limitedToNumberOfLines
최고, 중간 또는 하단 수직 정렬에 대한 올바른 경계를 반환합니다. 코드는 다음과 같습니다.
SOLabel.h
#import <UIKit/UIKit.h>
typedef enum
{
VerticalAlignmentTop = 0, // default
VerticalAlignmentMiddle,
VerticalAlignmentBottom,
} VerticalAlignment;
@interface SOLabel : UILabel
@property (nonatomic, readwrite) VerticalAlignment verticalAlignment;
@end
SOLabel.m
@implementation SOLabel
-(id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (!self) return nil;
// set inital value via IVAR so the setter isn't called
_verticalAlignment = VerticalAlignmentTop;
return self;
}
-(VerticalAlignment) verticalAlignment
{
return _verticalAlignment;
}
-(void) setVerticalAlignment:(VerticalAlignment)value
{
_verticalAlignment = value;
[self setNeedsDisplay];
}
// align text block according to vertical alignment settings
-(CGRect)textRectForBounds:(CGRect)bounds
limitedToNumberOfLines:(NSInteger)numberOfLines
{
CGRect rect = [super textRectForBounds:bounds
limitedToNumberOfLines:numberOfLines];
CGRect result;
switch (_verticalAlignment)
{
case VerticalAlignmentTop:
result = CGRectMake(bounds.origin.x, bounds.origin.y,
rect.size.width, rect.size.height);
break;
case VerticalAlignmentMiddle:
result = CGRectMake(bounds.origin.x,
bounds.origin.y + (bounds.size.height - rect.size.height) / 2,
rect.size.width, rect.size.height);
break;
case VerticalAlignmentBottom:
result = CGRectMake(bounds.origin.x,
bounds.origin.y + (bounds.size.height - rect.size.height),
rect.size.width, rect.size.height);
break;
default:
result = bounds;
break;
}
return result;
}
-(void)drawTextInRect:(CGRect)rect
{
CGRect r = [self textRectForBounds:rect
limitedToNumberOfLines:self.numberOfLines];
[super drawTextInRect:r];
}
@end
답변
StoryBoard에서 AutoLayout을 사용하는 솔루션을 찾았습니다.
1) 줄 수를 0으로, 텍스트 정렬을 왼쪽으로 설정합니다.
2) 높이 제한을 설정합니다.
3) 높이 제약은 관계식이어야합니다-작거나 같음
4)
override func viewWillLayoutSubviews() {
sampleLabel.sizeToFit()
}
결과는 다음과 같습니다.
답변
SOLabel이 저에게 효과적입니다.
Swift 3 및 5 :
이 버전은 RTL 언어를 지원하도록 원본에서 업데이트되었습니다.
public class VerticalAlignLabel: UILabel {
enum VerticalAlignment {
case top
case middle
case bottom
}
var verticalAlignment : VerticalAlignment = .top {
didSet {
setNeedsDisplay()
}
}
override public func textRect(forBounds bounds: CGRect, limitedToNumberOfLines: Int) -> CGRect {
let rect = super.textRect(forBounds: bounds, limitedToNumberOfLines: limitedToNumberOfLines)
if UIView.userInterfaceLayoutDirection(for: .unspecified) == .rightToLeft {
switch verticalAlignment {
case .top:
return CGRect(x: self.bounds.size.width - rect.size.width, y: bounds.origin.y, width: rect.size.width, height: rect.size.height)
case .middle:
return CGRect(x: self.bounds.size.width - rect.size.width, y: bounds.origin.y + (bounds.size.height - rect.size.height) / 2, width: rect.size.width, height: rect.size.height)
case .bottom:
return CGRect(x: self.bounds.size.width - rect.size.width, y: bounds.origin.y + (bounds.size.height - rect.size.height), width: rect.size.width, height: rect.size.height)
}
} else {
switch verticalAlignment {
case .top:
return CGRect(x: bounds.origin.x, y: bounds.origin.y, width: rect.size.width, height: rect.size.height)
case .middle:
return CGRect(x: bounds.origin.x, y: bounds.origin.y + (bounds.size.height - rect.size.height) / 2, width: rect.size.width, height: rect.size.height)
case .bottom:
return CGRect(x: bounds.origin.x, y: bounds.origin.y + (bounds.size.height - rect.size.height), width: rect.size.width, height: rect.size.height)
}
}
}
override public func drawText(in rect: CGRect) {
let r = self.textRect(forBounds: rect, limitedToNumberOfLines: self.numberOfLines)
super.drawText(in: r)
}
}
스위프트 1 :
class UIVerticalAlignLabel: UILabel {
enum VerticalAlignment : Int {
case VerticalAlignmentTop = 0
case VerticalAlignmentMiddle = 1
case VerticalAlignmentBottom = 2
}
var verticalAlignment : VerticalAlignment = .VerticalAlignmentTop {
didSet {
setNeedsDisplay()
}
}
required init(coder aDecoder: NSCoder){
super.init(coder: aDecoder)
}
override func textRectForBounds(bounds: CGRect, limitedToNumberOfLines: Int) -> CGRect {
let rect = super.textRectForBounds(bounds, limitedToNumberOfLines: limitedToNumberOfLines)
switch(verticalAlignment) {
case .VerticalAlignmentTop:
return CGRectMake(bounds.origin.x, bounds.origin.y, rect.size.width, rect.size.height)
case .VerticalAlignmentMiddle:
return CGRectMake(bounds.origin.x, bounds.origin.y + (bounds.size.height - rect.size.height) / 2, rect.size.width, rect.size.height)
case .VerticalAlignmentBottom:
return CGRectMake(bounds.origin.x, bounds.origin.y + (bounds.size.height - rect.size.height), rect.size.width, rect.size.height)
default:
return bounds
}
}
override func drawTextInRect(rect: CGRect) {
let r = self.textRectForBounds(rect, limitedToNumberOfLines: self.numberOfLines)
super.drawTextInRect(r)
}
}
답변
제 경우에는 bottom space
제약 문제였습니다. 나는 그것을로 설정했다 = 16
.
로 설정하면 bottom to >= 16
이 문제가 해결되었습니다.
또한 레이블에 높이 제약이있는 경우이를 제거해야합니다.
크기 검사기에서 내 레이블의 제약보기는 다음과 같습니다.
답변
귀하의 코드에서
label.text = @"some text";
[label sizeToFit];
다른 데이터로 재활용되는 테이블 셀이나 다른 뷰에서이를 사용하는 경우 원본 프레임을 어딘가에 저장하고 sizeToFit을 호출하기 전에 재설정해야합니다.
답변
같은 문제에 대한 다른 해결책을 찾았습니다. UITextView
대신 사용 UILabel
하고 editable()
기능을 false
.