[Ios] قم بمحاذاة النص رأسياً لأعلى داخل UILabel


Answers

  1. قم بتعيين النص الجديد:

    myLabel.text = @"Some Text"
    
  2. قم بتعيين maximum number الأسطر إلى 0 (تلقائي):

    myLabel.numberOfLines = 0
    
  3. اضبط إطار التسمية على الحد الأقصى للحجم:

    myLabel.frame = CGRectMake(20,20,200,800)
    
  4. حجم المكالمة sizeToFit لتقليل حجم الإطار حتى تناسب المحتويات:

    [myLabel sizeToFit]
    

أصبح إطار التسميات الآن مرتفعًا وعريضًا بما يكفي ليتناسب مع النص الخاص بك. يجب ألا يتغير الجزء العلوي الأيسر. لقد اختبرت هذا فقط مع أعلى اليسار محاذاة النص. بالنسبة إلى محاذاة أخرى ، قد يتعين عليك تعديل الإطار بعد ذلك.

أيضًا ، تم تمكين التفاف الكلمة الخاصة بي.

Question

لدي UILabel مع مساحة UILabel من النص. في بعض الأحيان ، عندما يكون النص قصيرًا جدًا ، يتم عرض هذا النص في المركز الرأسي للملصق.

كيف أقوم بمحاذاة النص رأسياً ليكون دائماً في قمة UILabel ؟




In UILabel vertically text alignment is not possible. But, you can dynamically change the height of the label using sizeWithFont: method of NSString , and just set its x and y as you want.

You can use UITextField . It supports the contentVerticalAlignment peoperty as it is a subclass of UIControl . You have to set its userInteractionEnabled to NO to prevent user from typing text on it.




لقد وجدت أن الإجابات على هذا السؤال أصبحت قديمة بعض الشيء ، لذا أضفها إلى معجبي التخطيط التلقائي هناك.

يجعل التخطيط التلقائي هذه المشكلة تافهة جدًا. بفرض أننا سنضيف التسمية إلى UIView *view ، فإن التوليف التالي سيحقق ذلك:

UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
[label setText:@"Some text here"];
[label setTranslatesAutoresizingMaskIntoConstraints:NO];
[view addSubview:label];

[view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[label]|" options:0 metrics:nil views:@{@"label": label}]];
[view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[label]" options:0 metrics:nil views:@{@"label": label}]];

سيتم حساب ارتفاع التسمية تلقائيًا (باستخدام intrinsicContentSize ) وسيتم وضع العلامة على الحافة أفقياً في الجزء العلوي من view .




خلق فئة جديدة

LabelTopAlign

ملف

#import <UIKit/UIKit.h>


@interface KwLabelTopAlign : UILabel {

}

@end

م ملف

#import "KwLabelTopAlign.h"


@implementation KwLabelTopAlign

- (void)drawTextInRect:(CGRect)rect {
    int lineHeight = [@"IglL" sizeWithFont:self.font constrainedToSize:CGSizeMake(rect.size.width, 9999.0f)].height;
    if(rect.size.height >= lineHeight) {
        int textHeight = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(rect.size.width, rect.size.height)].height;
        int yMax = textHeight;
        if (self.numberOfLines > 0) {
            yMax = MIN(lineHeight*self.numberOfLines, yMax);    
        }

        [super drawTextInRect:CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, yMax)];
    }
}

@end

تصحيح

إليك تطبيق أبسط يفعل نفس الشيء:

#import "KwLabelTopAlign.h"

@implementation KwLabelTopAlign

- (void)drawTextInRect:(CGRect)rect
{
    CGFloat height = [self.text sizeWithFont:self.font
                            constrainedToSize:rect.size
                                lineBreakMode:self.lineBreakMode].height;
    if (self.numberOfLines != 0) {
        height = MIN(height, self.font.lineHeight * self.numberOfLines);
    }
    rect.size.height = MIN(rect.size.height, height);
    [super drawTextInRect:rect];
}

@end



طالما أنك لا تقوم بأي مهمة معقدة ، يمكنك استخدام UITextView بدلاً من UILabels .

تعطيل التمرير.

إذا كنت ترغب في عرض النص بشكل كامل فقط حجم المستخدمالتي sizeToFit sizeThatFits: الأساليب




في سريع ،

let myLabel : UILabel!

لجعل نص التسمية الخاص بك ملائمًا للشاشة وهو في الأعلى

myLabel.sizeToFit()

لجعل خط التسمية الخاص بك ملائمًا لعرض الشاشة أو حجم العرض المحدد.

myLabel.adjustsFontSizeToFitWidth = YES

وبعض textAlignment للتصنيف:

myLabel.textAlignment = .center

myLabel.textAlignment = .left

myLabel.textAlignment = .right

myLabel.textAlignment = .Natural

myLabel.textAlignment = .Justified




فئة فرعية UILabel وتقييد مستطيل الرسم ، مثل هذا:

- (void)drawTextInRect:(CGRect)rect
{
    CGSize sizeThatFits = [self sizeThatFits:rect.size];
    rect.size.height = MIN(rect.size.height, sizeThatFits.height);

    [super drawTextInRect:rect];
}

حاولت الحل الذي يشمل حشوة الخط الجديد وركض في سلوك غير صحيح في بعض الحالات. في تجربتي ، من السهل تقييد numberOfLines الرسم على النحو الوارد أعلاه من الفوضى باستخدام numberOfLines .

ملاحظة: يمكنك تخيل دعم UIViewContentMode بسهولة بهذه الطريقة:

- (void)drawTextInRect:(CGRect)rect
{
    CGSize sizeThatFits = [self sizeThatFits:rect.size];

    if (self.contentMode == UIViewContentModeTop) {
        rect.size.height = MIN(rect.size.height, sizeThatFits.height);
    }
    else if (self.contentMode == UIViewContentModeBottom) {
        rect.origin.y = MAX(0, rect.size.height - sizeThatFits.height);
        rect.size.height = MIN(rect.size.height, sizeThatFits.height);
    }

    [super drawTextInRect:rect];
}



لقد أخذت الاقتراحات هنا وأنشأت عرضًا يمكن أن يلف UILabel وسيحجمه ويضبط عدد الأسطر بحيث يكون متماسكًا بشكل علوي. ببساطة ، ضع UILabel كعرض فرعي:

@interface TopAlignedLabelContainer : UIView
{
}

@end

@implementation TopAlignedLabelContainer

- (void)layoutSubviews
{
    CGRect bounds = self.bounds;

    for (UILabel *label in [self subviews])
    {
        if ([label isKindOfClass:[UILabel class]])
        {
            CGSize fontSize = [label.text sizeWithFont:label.font];

            CGSize textSize = [label.text sizeWithFont:label.font
                                     constrainedToSize:bounds.size
                                         lineBreakMode:label.lineBreakMode];

            label.numberOfLines = textSize.height / fontSize.height;

            label.frame = CGRectMake(0, 0, textSize.width,
                 fontSize.height * label.numberOfLines);
        }
    }
}

@end



فقط في حال كان أي مساعدة لأحد ، كان لي نفس المشكلة ولكن تمكنت من حل المشكلة ببساطة عن طريق التبديل من استخدام UILabel إلى استخدام UITextView . أقدر هذا ليس للجميع لأن الوظيفة مختلفة قليلاً.

إذا قمت بالتبديل إلى استخدام UITextView ، يمكنك إيقاف تشغيل كافة خصائص Scroll View بالإضافة إلى تمكين تفاعل المستخدم ... UITextView ذلك على التصرف مثل التسمية.




لقد استخدمت الكثير من الأساليب المذكورة أعلاه ، وأريد فقط إضافة أسلوب سريع وقذر استخدمته:

myLabel.text = [NSString stringWithFormat:@"%@\n\n\n\n\n\n\n\n\n",@"My label text string"];

تأكد من أن عدد الخطوط الجديدة في السلسلة سيؤدي إلى أي نص لملء المساحة العمودية المتوفرة ، وتعيين UILabel لاقتطاع أي نص فيض.

لأن في بعض الأحيان جيدة بما فيه الكفاية جيدة بما فيه الكفاية .




بدلاً من UILabel يمكنك استخدام UITextField الذي يحتوي على خيار المحاذاة العمودية:

textField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
textField.userInteractionEnabled = NO; // Don't allow interaction



حل Storyboard: أبسط وأسهل طريقة هي تضمين Label في StackView وتعيين Axis StackView إلى Horizontal ، Alignment Top في Attribute Inspector من Storyboard.




كتبت وظيفة الاستخدام لتحقيق هذا الغرض. يمكنك إلقاء نظرة:

// adjust the height of a multi-line label to make it align vertical with top
+ (void) alignLabelWithTop:(UILabel *)label {
  CGSize maxSize = CGSizeMake(label.frame.size.width, 999);
  label.adjustsFontSizeToFitWidth = NO;

  // get actual height
  CGSize actualSize = [label.text sizeWithFont:label.font constrainedToSize:maxSize lineBreakMode:label.lineBreakMode];
  CGRect rect = label.frame;
  rect.size.height = actualSize.height;
  label.frame = rect;
}

.كيف تستعمل؟ (إذا تم إنشاء lblHello بواسطة أداة إنشاء الواجهة ، فقم بتخطي بعض تفاصيل UILabel)

lblHello.text = @"Hello World! Hello World! Hello World! Hello World! Hello World! Hello World! Hello World! Hello World!";
lblHello.numberOfLines = 5;
[Utils alignLabelWithTop:lblHello];

كتبت أيضًا على مدونتي http://fstoke.me/blog/?p=2819 : http://fstoke.me/blog/?p=2819




لا ضجة ، أي ضجة

@interface MFTopAlignedLabel : UILabel

@end


@implementation MFTopAlignedLabel

- (void)drawTextInRect:(CGRect) rect
{
    NSAttributedString *attributedText = [[NSAttributedString alloc]     initWithString:self.text attributes:@{NSFontAttributeName:self.font}];
    rect.size.height = [attributedText boundingRectWithSize:rect.size
                                            options:NSStringDrawingUsesLineFragmentOrigin
                                            context:nil].size.height;
    if (self.numberOfLines != 0) {
        rect.size.height = MIN(rect.size.height, self.numberOfLines * self.font.lineHeight);
    }
    [super drawTextInRect:rect];
}

@end

لا ضجة ، لا الهدف ، ج ، لا ضجة ولكن سويفت 3:

class VerticalTopAlignLabel: UILabel {

    override func drawText(in rect:CGRect) {
        guard let labelText = text else {  return super.drawText(in: rect) }

        let attributedText = NSAttributedString(string: labelText, attributes: [NSFontAttributeName: font])
        var newRect = rect
        newRect.size.height = attributedText.boundingRect(with: rect.size, options: .usesLineFragmentOrigin, context: nil).size.height

        if numberOfLines != 0 {
            newRect.size.height = min(newRect.size.height, CGFloat(numberOfLines) * font.lineHeight)
        }

        super.drawText(in: newRect)
    }

}



إنشاء فئة فرعية من UILabel. يعمل كالسحر:

// TopLeftLabel.h

#import <Foundation/Foundation.h>

@interface TopLeftLabel : UILabel 
{
}

@end

// TopLeftLabel.m

#import "TopLeftLabel.h"

@implementation TopLeftLabel

- (id)initWithFrame:(CGRect)frame 
{
    return [super initWithFrame:frame];
}

- (CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)numberOfLines 
{
    CGRect textRect = [super textRectForBounds:bounds limitedToNumberOfLines:numberOfLines];    
    textRect.origin.y = bounds.origin.y;
    return textRect;
}

-(void)drawTextInRect:(CGRect)requestedRect 
{
    CGRect actualRect = [self textRectForBounds:requestedRect limitedToNumberOfLines:self.numberOfLines];
    [super drawTextInRect:actualRect];
}

@end

كما ناقشنا here .