[Iphone] كيفية تعيين المحاذاة العلوية ل UILabel لتطبيق iOS؟


Answers

من السهل القيام به. إنشاء UILabel UILabel مع خاصية 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
Question

لقد أضفت تصنيفًا واحدًا في ملف nib الخاص بي ، ثم كان مطلوبًا أن يكون المحاذاة في أعلى يمين لذلك lable. كما أقوم بتوفير النص في وقت التشغيل لذلك ليس متأكدا من مدى الخطوط هناك. لذا إذا احتوى النص على سطر واحد فقط ، فسيظهر على هيئة محاذاة رأسية. هذا التوافق لا يتوافق مع رأيي أمامه.

فمثلا:

والتي تبدو غريبة :(

هل هناك أي طريقة حيث يمكنني تعيين نص التسمية المناسبة لمحاذاة أعلى اليسار؟




كنت أواجه هذه المشكلة أيضًا لكن ما وجدته هو الترتيب الذي تضع فيه خصائص وخصائص UILabel!

إذا كنت تتصل بـ [label sizeToFit] قبل label.font = [UIFont fontWithName:@"Helvetica" size:14]; ثم لا محاذاة النص إلى الأعلى ولكن إذا كنت مبادلة حولها ، فإنه يفعل ذلك!

لاحظت أيضًا أن إعداد النص يُحدث فارقًا أيضًا.

أتمنى أن يساعدك هذا.




لقد وجدت حلًا باستخدام AutoLayout في StoryBoard.

1) تعيين أي من الخطوط إلى 0 ومحاذاة النص إلى اليسار.

2) ضبط ارتفاع الارتفاع.

3) يجب أن يكون القيد الارتفاع في العلاقة - أقل من أو يساوي

4)

   override func viewWillLayoutSubviews() {
        sampleLabel.sizeToFit()
    }

حصلت على النتيجة على النحو التالي:




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




أثناء استخدامك لواجهة الواجهة ، قم بتعيين قيود التسمية (تأكد من ضبط الارتفاع والعرض أيضًا). ثم في Size Inspector ، تحقق من ارتفاع التسمية. هناك سترغب في قراءتها> = بدلاً من =. ثم في تطبيق وحدة التحكم في العرض هذه ، قم بتعيين عدد الأسطر إلى 0 (يمكن أيضًا تنفيذه في IB) وتعيين التسمية [label labelToFit]؛ وعندما يكسب طول النص الخاص بك ، ستنمو التسمية في الارتفاع وتبقي النص الخاص بك في أعلى اليسار.




Swift 2.0 :: Using UILabel Extension

قم بعمل قيم التعداد المستمر في ملف Swift فارغ.

//  AppRef.swift

import UIKit
import Foundation

enum UILabelTextPositions : String {

 case VERTICAL_ALIGNMENT_TOP = "VerticalAlignmentTop"
 case VERTICAL_ALIGNMENT_MIDDLE = "VerticalAlignmentMiddle"
 case VERTICAL_ALIGNMENT_BOTTOM = "VerticalAlignmentBottom"

}

باستخدام UILabel Extension:

قم بإعداد فصيلة Swift فارغة واسمها. أضف ما يلي.

//  AppExtensions.swift

import Foundation
import UIKit

    extension UILabel{ 
     func makeLabelTextPosition (sampleLabel :UILabel?, positionIdentifier : String) -> UILabel
     {
      let rect = sampleLabel!.textRectForBounds(bounds, limitedToNumberOfLines: 0)

      switch positionIdentifier
      {
      case "VerticalAlignmentTop":
       sampleLabel!.frame = CGRectMake(bounds.origin.x+5, bounds.origin.y, rect.size.width, rect.size.height)
       break;

      case "VerticalAlignmentMiddle":
       sampleLabel!.frame = CGRectMake(bounds.origin.x+5,bounds.origin.y + (bounds.size.height - rect.size.height) / 2,
        rect.size.width, rect.size.height);
       break;

      case "VerticalAlignmentBottom":
       sampleLabel!.frame = CGRectMake(bounds.origin.x+5, bounds.origin.y + (bounds.size.height - rect.size.height),rect.size.width, rect.size.height);
       break;

      default:
       sampleLabel!.frame = bounds;
       break;
      }
      return sampleLabel!

     }
    }

الاستعمال:

myMessageLabel.makeLabelTextPosition(messageLabel, positionIdentifier: UILabelTextPositions.VERTICAL_ALIGNMENT_TOP.rawValue)



استنادًا إلى الإجابة المذهلة لـ totiG ، لقد قمت بإنشاء فئة IBDesignable التي تجعل من السهل للغاية تخصيص محاذاة رأسية UILabel مباشرة من StoryBoard. فقط تأكد من تعيين فئة UILabel إلى "VerticalAlignLabel" من عارض الهوية StoryBoard. إذا كان المحاذاة العمودية غير نافذة المفعول ، فانتقل إلى Editor-> Refresh All Views الذي يجب أن يؤدي المهمة.

كيف يعمل: بمجرد تعيين صف UILabel الخاص بك بشكل صحيح ، يجب أن تعرض لوحة العمل حقل إدخال يأخذ عددًا صحيحًا (رمز المحاذاة).

تحديث: لقد أضفت دعمًا للتسميات المركزية ~

أدخل 0 لأعلى محاذاة

أدخل 1 لمحاذاة الأوسط

أدخل 2 لمحاذاة سفلية

    @IBDesignable class VerticalAlignLabel: UILabel {
    
    @IBInspectable var alignmentCode: Int = 0 {
        didSet {
            applyAlignmentCode()
        }
    }
    
    func applyAlignmentCode() {
        switch alignmentCode {
        case 0:
            verticalAlignment = .top
        case 1:
            verticalAlignment = .topcenter
        case 2:
            verticalAlignment = .middle
        case 3:
            verticalAlignment = .bottom
        default:
            break
        }
    }
    
    override func awakeFromNib() {
        super.awakeFromNib()
        self.applyAlignmentCode()
    }
    
    override func prepareForInterfaceBuilder() {
        super.prepareForInterfaceBuilder()
        
        self.applyAlignmentCode()
    }
    
    enum VerticalAlignment {
        case top
        case topcenter
        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 #available(iOS 9.0, *) {
            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 .topcenter:
                    return CGRect(x: self.bounds.size.width - (rect.size.width / 2), 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 .topcenter:
                    return CGRect(x: (self.bounds.size.width / 2 ) - (rect.size.width / 2), 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)
                }
            }
        } else {
            // Fallback on earlier versions
            return rect
        }
    }
    
    override public func drawText(in rect: CGRect) {
        let r = self.textRect(forBounds: rect, limitedToNumberOfLines: self.numberOfLines)
        super.drawText(in: r)
    }
}




Links