2014-11-13 13 views
19

Ich habe ein Beispielprojekt erstellt, um dies zu reproduzieren.Autolayout Hinzufügen von zusätzlicher Polsterung oben und unten von UILabel iPhone 6/6 +, wenn preferredMaxLayoutWidth

Ich habe eine XIB-Datei mit einem UILabel mit einer festen oberen, führenden und nachfolgenden Einschränkung. Ich habe eine MinHeight-Einschränkung hinzugefügt und die Anzahl der Zeilen auf 0 gesetzt.

Ich legte die preferredMaxLayoutWidth auf Automatisch (in der XIB-Datei überprüft).

In viewDidLoad, ich habe dies:

self.myLabel.layer.borderColor = [[UIColor redColor] CGColor]; 
self.myLabel.layer.borderWidth = 2.0f; 
self.myLabel.text = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."; 

Und wenn ich den Simulator auf iPhone 6 oder 6+ laufen, bekomme ich diese:

enter image description here

Ich habe keine Ahnung, woher diese obere und untere Polsterung kommt und ist proportional zu th Die Anzahl der Zeichen in UILabel wird angezeigt.

Gibt es eine magische Einstellung, die ich vergessen habe? Es läuft gut auf iPhone 4 "Geräte.

Wenn ich jetzt nicht die preferredMaxLayoutWidth, hat es nicht die zusätzliche Polsterung, aber das bricht meine Multi-Zeilen in der UILabel. Es schneidet den Text. Ich tat verwendet Größe-Klasse nicht

Edit:..

Also änderte ich einige Dinge in meinem Beispielprojekt die Situation auf meinem realen Projekt passen ich habe eine Tableview (mit oben hinzugefügt, den führenden, Boden und trailing constraints auf die übergeordnete Ansicht gesetzt. Jede Zelle in der tableView hat 4 Label. Das obere Label hat eine obere, führende und nachstehende Einschränkung für die contentView der Zelle und die nachfolgenden Labels haben eine Vertic al Einschränkung auf das Etikett darüber. Für jedes Label gibt es einen heightGreaterThan-Constraint-Satz und einen widthGreaterThan-Satz.

So sieht es ohne den preferredMaxLayoutWidth-Satz aus (Beachten Sie, wie Beschriftungen auf 1 Zeile begrenzt sind). No preferredMaxLayoutWidth

Mit preferredMaxLayoutWidth. Jetzt zeigt das UILabel den gesamten Inhalt, hat aber oben und unten eine Auffüllung. With preferredMaxLayoutWidth but with top and bottom padding

Edit2: Beispielprojekt: https://www.dropbox.com/s/sdahx9njnsxiv98/MultiLineUILabel.zip?dl=1

+1

ich genau das gleiche Problem wie Sie. Ich habe sogar versucht, die 'preferredMaxLayoutWidth' durch Hinzufügen einiger Pixel zu hacken, aber diese Zahl hängt stark davon ab, wie breit der Bildschirm ist und rendert auf iPhone 6, iPhone 6+ und iPhone 5. Ganz zu schweigen von iPad. Nicht sicher, ob es sich um einen Fehler handelt oder ob es andere Einstellungen/Hacks gibt, damit es funktioniert. –

+0

Ich hatte das gleiche Problem und ich habe nicht Auto-Layout verwendet. Das Problem trat nur auf dem iPhone 6 und nicht auf dem iPad auf. Keine Kombination von Autoresize-Maskeneinstellungen machte einen Unterschied. Schließlich habe ich das Problem gelöst, indem ich einen Clean, Restart XCode und Rebuild gemacht habe. Seltsam, aber es löst das Problem, wo ein Clean alleine nicht wäre. XCode 6.1.1. – JasonD

+2

Stellen Sie sicher, dass die bevorzugte Breite des Labels auf "Automatisch" eingestellt ist und dass "Explizit" im Einstellungsfenster nicht aktiviert ist. Dies löste das Problem für mich bei der Verwendung von Autotuning. – AndyC

Antwort

6

Also, was ich tun gelandet war, eine Unterklasse für das Label zu erstellen und setBounds außer Kraft setzen: und die preferredMaxLayoutWidth seiner Grenzen gesetzt.

- (void)setBounds:(CGRect)bounds { 
    [super setBounds:bounds]; 

    if (self.preferredMaxLayoutWidth != bounds.size.width) { 
     self.preferredMaxLayoutWidth = bounds.size.width; 
     [self setNeedsUpdateConstraints]; 
}} 

Auch in der UITableViewCell Unterklasse überschreiben ich die layoutSubiews

- (void)layoutSubviews { 
    [super layoutSubviews]; 

    [self.contentView layoutIfNeeded]; 

    // labelsCollection is an IBOutletCollection of my UILabel sublasses 
    for (UILabel *label in self.labelsCollection) { 
     label.preferredMaxLayoutWidth = label.bounds.size.width; 
}} 

Dies funktioniert die ganze Zeit. Ich denke, der Grund für dieses seltsame Verhalten ist, dass das UILabel anfänglich auf 280px (320px - Auffüllen auf jeder Seite) in der Xib-Datei eingestellt ist, aber während der Laufzeit ändert es seine Breite, um größere Bildschirme aufzunehmen (seit ich das führende und das nachfolgende gesetzt habe) constraints erhöht die Breite, wodurch die 'preferredMaxLayoutWidth' in einen größeren Wert geändert wird. Aus irgendeinem Grund aktualisiert UILabel seine preferredMaxLayoutWidth nicht auf den größeren Wert und verursacht den Leerraum oben und unten.

Das ist meine Hypothese.

Hoffe, das hilft.

+0

Ich weiß, das ist alt, jede Änderung, die Sie auch in Swift? Da es keine SetBounds-Funktion hat. –

+0

Nvm bekam es, mit Get & Set und beziehen sich auf supe r.bounds innerhalb von denen get & set funktioniert gut. –

+1

@MathijsSegers Können Sie näher erläutern, wie Sie dies zum Funktionieren gebracht haben? – hundley

0

UILabel Zentren Text vertikal. Ich nehme an, dass Sie sehen, dass Ihre Einschränkungen dazu führen, dass sich die Ansicht des Labels auf dem größeren Gerät ausdehnt, und der Text zentriert sich wie erwartet vertikal auf der großen Ansicht.

Sie könnten stattdessen versuchen, ein nicht editierbares UITextView mit UIViewContentModeTop zu verwenden.

+0

So fügt das Padding am unteren Rand der textView. [TextView] (http://i.imgur.com/e0ZGrWU.png) Edit: Ich sollte klarstellen, dass die Höhe der textView im Code dynamisch eingestellt ist und es nur 1 Zeile hoch in der Xib ist. – newDeveloper

+0

Wenn Sie die Größe des Textes im Voraus kennen, können Sie eine Beschränkung für die Höhe und Breite für das Etikett festlegen und sicherstellen, dass das Format wie gewünscht formatiert wird. Auch jetzt, wo ich Ihre Änderungen ansehe, haben Sie Zeilenumbrüche auf Word Wrap? Es scheint nicht, dass der Text so verpackt ist, wie Sie möchten. – stromdotcom

+0

Das ist mein letzter Ausweg. Idealerweise möchte ich, dass das Autolayout es handhabt (und es behandelt es gut auf iPhone 4 "und kleineren Bildschirmen). Das Ändern des Zeilenumbrüches ändert nichts an dem tatsächlichen Problem (es ändert, wo es die Zeile unterbricht oder das ... zeigt). – newDeveloper

0

Gibt es Einschränkungen auf der Unterseite des Etiketts? Ich glaube, es ist erlaubt, sich wegen der inhaltlichen Umarmung zu strecken. Setze es auf 1000 (erforderlich). Das wird verhindern, dass es sich über seine Textgröße hinaus ausdehnt. Sie müssen dann am unteren Ende des Etiketts die richtigen Einschränkungen hinzufügen.

+0

Ja, ich habe eine untere vertikale Einschränkung vom Label zum parentView (mit weniger Priorität als die anderen) und habe die horizontale und vertikale Content-Umgehungspriorität auf 1000 eingestellt. – newDeveloper

+0

Ok. Es sieht fast wie die Höhe aus berechnet ist für ein 4-Zoll-Gerät, aber dann ist die Breite für größere Gerät gestreckt. Können Sie Beispielprojekt? –

+0

Sure, https://www.dropbox.com/s/sdahxnnxnsxiv98/MultiLineUILabel.zip?dl=1 Ich schaltete die aus preferredMaxLayoutWidth. Schalten Sie es ein, um Multi-Line-Label zu sehen. – newDeveloper

0

Da ich PreferredMaxLayoutWidth für iOS 7-Kompatibilität festlegen musste, rief ich schließlich boundingRectWithSize auf, um die erforderliche Label-Höhe zu berechnen und die Konstante einer exponierten Höhenbeschränkung für UILabel festzulegen.

CGRect labelRect = CGRectIntegral([myText boundingRectWithSize:size 
    options:options attributes:attributes context:context]); 
self.myLabelHeightConstraint.constant = labelRect.size.height; 
0

So habe ich dies auf swift implementiert, In der Klasse, die das UILabel erweitert, überschreibe ich die Grenzen var mit einem Getter und Setter, der die Grenzen des Super legt und zurückgibt, auf diese Weise können Sie etwas Code hinzufügen um das zu bekommen und einzustellen.

Ich muss sagen, ich bin nicht überzeugt, dass es die ganze Magie gerade macht, ich habe immer noch große offene Räume.

override var bounds:CGRect { 
     get { 
      return super.bounds 
     } 
     set { 
      super.bounds = newValue 
      if (self.preferredMaxLayoutWidth != super.bounds.size.width) { 
       self.preferredMaxLayoutWidth = super.bounds.size.width; 
       self.setNeedsUpdateConstraints() 
      } 
     } 
    } 
+0

für den Rekord, Es ändert sich nicht die Höhe, es wäre nett, wenn jemand das gelöst hat. um es zu diesem Thema wissen zu lassen. –

0

Vor allem Jungs, Entschuldigung für mein Englisch. Ich bin Anfänger auf Englisch, aber ich werde versuchen zu beschreiben, wie ich dieses Problem behoben habe.

Ich habe in einigen meiner Projekte mit diesem Problem konfrontiert. Also meine Lösung, dies zu beheben ist:

  1. In einer Zelle habe ich die folgende Konfigurationsmethode: - (void) configureWithSomeObject: parentViewSize: und in Tableview: cellForRowAtIndexPath: Ich Zelle wie folgt erstellt:

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
    YourCell *cell; 
    
    //cell initialization 
    
    [cell configureWithSomeObject:nil parentViewSize:tableView.frame.size]; 
    
    return cell; 
    } 
    
  2. Innenkonfigurationsmethoden gerade eingestellt preferredMaxLayoutWidth gemäß Mutterbreite:

    - (void)configureWithSomeObject:(NSObject)someObject parentViewSize:(CGSize)parentViewSize { 
    // do your stuff 
    
    self.someLabel.preferredMaxLayoutWidth = parentViewSize.width; 
    } 
    

P.S. Falls Sie führende/nachgestellte Leerzeichen haben, sollten Sie sie vom Wert parentViewSize.width subtrahieren.

Hoffen, dass es für jeden nützlich sein wird :)

0

ich ein ähnliches Problem habe, und nur Subklassen die UILabel und überwiegende setBounds nicht für mich arbeiten. Als ich durch setBounds ging, bemerkte ich, dass die Höhe des Etiketts 39,999999993 war.Also habe ich die folgende Änderung, auf 40 abzurunden:

- (void)setBounds:(CGRect)bounds 
{ 
    bounds.size.height = ceilf(CGRectGetHeight(bounds)); 

    [super setBounds: bounds]; 

    if (self.preferredMaxLayoutWidth != bounds.size.width) 
    { 
     self.preferredMaxLayoutWidth = bounds.size.width; 
     [self setNeedsUpdateConstraints]; 
    } 
} 

Dieses es für mich festgelegt, nicht mehr extra Polsterung oben und unten meine UILabel auf große Geräte. Ich musste auch nicht die inhaltliche Priorität festlegen.

1

Wenn jemand diese Frage untersucht, die bereits maxPreferredLayoutWidth verwendet (obwohl Sie keine Unterklasse erstellen müssen, setzen Sie dies einfach in viewDidLayoutSubviews Ihrer VC), überprüfen Sie, ob Sie ihn auf die Breite der richtigen Ansicht einstellen.

Minen funktionierte nicht, weil ich hatte:

label1.maxPreferredLayoutWidth = label1.frame.width 
label2.maxPreferredLayoutWidth = label1.frame.width 

Wenn es hätte sein sollen:

label1.maxPreferredLayoutWidth = label1.frame.width 
label2.maxPreferredLayoutWidth = label2.frame.width 

Haben Sie den Unterschied? Ich habe nicht für 3 Stunden lol

+1

Für alle, die nicht sehen ...Es ist 'label1' gegen' label2' nach den '=' Zeichen in den zweiten Zeilen – BallpointBen

1

diese Klasse es fest mit mir

import UIKit 

class CustomLabel: 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) 
     } 
    } 

} 
Verwandte Themen