[iphone] iOS 애플리케이션 용 UILabel의 왼쪽 상단 정렬을 설정하는 방법은 무엇입니까?

내 펜촉 파일에 레이블 하나를 추가 한 다음 해당 레이블에 대해 왼쪽 상단 정렬이 필요합니다. 런타임에 텍스트를 제공하므로 얼마나 많은 줄이 있는지 확실하지 않습니다. 따라서 텍스트에 한 줄만 포함되어 있으면 세로 중앙 정렬로 나타납니다. 그 정렬은 그 앞에있는 내 각 레이블과 일치하지 않습니다.

예를 들면 :

여기에 이미지 설명 입력

이상하게 보입니다 🙁

레이블 텍스트를 왼쪽 위 정렬에 맞게 설정할 수있는 방법이 있습니까?



답변

다시 설명하기보다는 다소 광범위하고 높은 등급의 질문 / 답변을 링크하겠습니다.

UILabel 내에서 상단에 텍스트를 수직으로 정렬

짧은 대답은 아니오입니다. Apple은 이것을 쉽게 만들지 않았지만 프레임 크기를 변경하면 가능합니다.


답변

매우 쉽습니다. 크리에이트 UILabelA를 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.