wake-up-neo.net

Text innerhalb eines UILabels vertikal ausrichten (Hinweis: Verwenden von AutoLayout)

Ich kopiere dieselbe Frage vor Frage . Ich habe die angegebenen Lösungen ausprobiert und konnte sie nicht lösen, da sizetofit bei Verwendung von Autolayout nicht wirksam war.

first screenshot

Die erwartete Anzeige ist wie folgt.

second screenshot

61
MELWIN

Bearbeiten

In meiner ursprünglichen Antwort habe ich den Absatzstil des Labels verwendet. Es stellt sich heraus, dass bei mehrzeiligen Etiketten tatsächlich verhindert wird, dass das Etikett mehrzeilig ist. Als Ergebnis habe ich es aus der Berechnung entfernt. Mehr dazu in Github

Für diejenigen, die sich mit Open Source besser auskennen, schauen Sie auf jeden Fall nach TTTAttributedLabel , wo Sie die Textausrichtung des Labels auf TTTAttributedLabelVerticalAlignmentTop setzen können.


Der Trick ist die Unterklasse UILabel und die Überschreibung von drawTextInRect. Erzwingen Sie dann, dass der Text am Ursprung der Grenzen des Etiketts gezeichnet wird.

Hier ist eine naive Implementierung, die Sie jetzt verwenden können:

Schnell

@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
    }
}

Swift 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
    }
}

Ziel 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

Da ich IBDesignable verwendet habe, können Sie dieses Label zu einem Storyboard hinzufügen und sehen, wie es läuft. So sieht es für mich aus

enter image description here

128
Daniel Galasko

Wenn Sie nicht durch UILabel mit fester Größe eingeschränkt sind, verwenden Sie , anstatt den Text innerhalb eines UILabels auszurichten, einfach die Einschränkung ≥ für das angegebene Label, um die Größe des Labels zu ändern.

 enter image description here

Es ist die eleganteste Lösung mit Auto Layout. Vergessen Sie nicht, numberOfLines auf Null zu setzen.

37

Sie können UITextView anstelle von UILabel verwenden:
Deaktivieren Sie "Scrollen aktiviert".
Deaktivieren Sie "Bearbeitbar".
Deaktivieren Sie "Auswählbar".
Hintergrundfarbe auf ClearColor setzen

32
arturdev

Ich hatte das gleiche Problem und so habe ich es gelöst. Ich habe gerade die Grundlinie unter Attribute Inspector für das Label bearbeitet. Stellen Sie es auf "Zentren ausrichten".

 Setting baseline to Align Centers

8
Oyvkva

Stattdessen habe ich die untere Raumkonstante auf Priorität @ 250 geändert und mein Problem gelöst. Und mein Etikett hat konstant eine konstante Höhe

7
Felipe FMMobile

Sie würden das tun, indem Sie die minimale Höhe entfernen.

Wenn Sie die Mindesthöhe für etwas anderes unterhalb des Etiketts benötigen, verwenden Sie eine Containeransicht, deren Größe basierend auf dem Etiketteninhalt angepasst, jedoch ein Minimum verwendet wird.

4
Wain

Es gibt eine einfache Lösung für Fälle, in denen die Höhe einer Beschriftung nicht konstant sein muss: Geben Sie Ihr Label in ein Stack View ein. Stellen Sie sicher, dass Sie dem Stack View führende und nachgestellte Konstanten hinzufügen. Hier ist ein Screenshot, wie man das im Storyboard macht:

 enter image description here

1

Ich habe die Lösung von @Daniel Golasko verwendet. Immer wenn der Text im UILabel länger war als das UILabel enthalten konnte, bewegte sich der Text nach unten, anstatt an der Spitze ausgerichtet zu bleiben.

Ich habe diese Zeile geändert, um sicherzustellen, dass der Text richtig ausgerichtet ist

    [super drawTextInRect:CGRectMake(0, 0, ceilf(CGRectGetWidth(self.frame)),MIN(ceilf(labelStringSize.height), self.frame.size.height))];
1
ezchen

Schnell 4

Sie sollten UILabel als Unterklasse definieren und die Wiedergabe von Textanzeigen überschreiben.

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)
    }
}
1
dimpiax

Ich hatte ein ähnliches Problem, bei dem es 3 Labels gab. Das mittlere Etikett könnte einen viel längeren Text haben als die anderen beiden, sodass seine Höhe viel größer werden könnte. 

So was:

 enter image description here

Ich habe die Einschränkung für den unteren Abstand des mittleren Labels auf> = das untere Label gesetzt.

 enter image description here

Das hat mein Problem gelöst.

1

Auto-Layout funktioniert nur mit Kanten/Größen des Controllers, nicht mit Controller-Inhalten. Daher ist es keine gute Idee, das Auto-Layout zu verwenden, um Ihren Beschriftungstext über der ersten Zeile anzuzeigen so.

1
EI Captain v2.0
  @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()
      }
    }
  }
0
hojin

Sie können versuchen, wenn die Schaltfläche [button setContentVerticalAlignment:UIControlContentVerticalAlignmentTop];

Bearbeiten: 

Sie können dies versuchen, wenn Sie nur das Etikett verwenden möchten:

https://stackoverflow.com/a/11278660/1223897

0
Yuvrajsinh

use dies ist meine Klasse, Sie können den Text alignment durch contentMode ändern. 

unterstützter Fall: .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)
        }
    }

}
0
EvGeniy Ilyin

Hier ist eine Verbesserung der Swift 3-Lösung von Daniel Galasko (hier können Sie auch die maximale Zeilennummer ohne Versatz oben einstellen):

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
    }
}
0
Onno Eberhard

Für mich habe ich die Höhenbeschränkung nicht festgelegt, der Text wächst immer vom oberen Rand der Beschriftung aus .. Die Einschränkungen für diese Beschriftung sind oben, links und rechts Zahlen, also keine Sorgen über die Höhe.

0
Xiang LI