Κάθετη ευθυγράμμιση του κειμένου προς τα πάνω μέσα σε μια UILabel

Έχω μια UILabel με χώρο για δύο γραμμές κειμένου. Μερικές φορές, όταν το κείμενο είναι πολύ μικρό, το κείμενο αυτό εμφανίζεται στο κάθετο κέντρο της ετικέτας.

Πώς μπορώ να ευθυγραμμίσω κάθετα το κείμενο ώστε να βρίσκεται πάντα στο επάνω μέρος της UILabel;

Λύση

Δεν υπάρχει τρόπος να ορίσετε την κατακόρυφη στοίχιση σε μια UILabel, αλλά μπορείτε να έχετε το ίδιο αποτέλεσμα αλλάζοντας το πλαίσιο της ετικέτας. Έκανα τις ετικέτες μου πορτοκαλί για να μπορείτε να δείτε καθαρά τι συμβαίνει.

Εδώ είναι ο γρήγορος και εύκολος τρόπος για να το κάνετε αυτό:

    [myLabel sizeToFit];

![sizeToFit για να συμπιέσετε μια ετικέτα][1]


Αν έχετε μια ετικέτα με μεγαλύτερο κείμενο που θα κάνει περισσότερες από μια γραμμές, ορίστε το numberOfLines σε 0 (το μηδέν εδώ σημαίνει απεριόριστο αριθμό γραμμών).

    myLabel.numberOfLines = 0;
    [myLabel sizeToFit];

![Μεγαλύτερο κείμενο ετικέτας με sizeToFit][2]


Μακρύτερη έκδοση

Θα φτιάξω την ετικέτα μου σε κώδικα ώστε να μπορείτε να δείτε τι συμβαίνει. Μπορείτε να ρυθμίσετε τα περισσότερα από αυτά και στο Interface Builder. Η δική μου ρύθμιση είναι μια View-Based App με μια εικόνα φόντου που έφτιαξα στο Photoshop για να δείξω τα περιθώρια (20 σημεία). Η ετικέτα έχει ένα ελκυστικό πορτοκαλί χρώμα ώστε να μπορείτε να δείτε τι'συμβαίνει με τις διαστάσεις.

- (void)viewDidLoad
{
    [super viewDidLoad];

    // 20 point top and left margin. Sized to leave 20 pt at right.
    CGRect labelFrame = CGRectMake(20, 20, 280, 150);
    UILabel *myLabel = [[UILabel alloc] initWithFrame:labelFrame];
    [myLabel setBackgroundColor:[UIColor orangeColor]];

    NSString *labelText = @"I am the very model of a modern Major-General, I've information vegetable, animal, and mineral";
    [myLabel setText:labelText];

    // Tell the label to use an unlimited number of lines
    [myLabel setNumberOfLines:0];
    [myLabel sizeToFit];

    [self.view addSubview:myLabel];
}

Κάποιοι περιορισμοί της χρήσης του sizeToFit μπαίνουν στο παιχνίδι με κείμενο που είναι στοιχισμένο στο κέντρο ή δεξιά. Ακούστε τι συμβαίνει:

    // myLabel.textAlignment = NSTextAlignmentRight;
    myLabel.textAlignment = NSTextAlignmentCenter;

    [myLabel setNumberOfLines:0];
    [myLabel sizeToFit];

![εισάγετε την περιγραφή της εικόνας εδώ][3]

Η ετικέτα εξακολουθεί να έχει μέγεθος με σταθερή πάνω αριστερή γωνία. Μπορείτε να αποθηκεύσετε το αρχικό πλάτος της ετικέτας σε μια μεταβλητή και να το ορίσετε μετά το sizeToFit, ή να της δώσετε ένα σταθερό πλάτος για να αντιμετωπίσετε αυτά τα προβλήματα:

    myLabel.textAlignment = NSTextAlignmentCenter;

    [myLabel setNumberOfLines:0];
    [myLabel sizeToFit];

    CGRect myFrame = myLabel.frame;
    // Resize the frame's width to 280 (320 - margins)
    // width could also be myOriginalLabelFrame.size.width
    myFrame = CGRectMake(myFrame.origin.x, myFrame.origin.y, 280, myFrame.size.height);
    myLabel.frame = myFrame;

![ευθυγράμμιση ετικέτας][4]


Σημειώστε ότι το sizeToFit θα σεβαστεί το ελάχιστο πλάτος της αρχικής σας ετικέτας. Αν ξεκινήσετε με μια ετικέτα πλάτους 100 και καλέσετε το sizeToFit σε αυτήν, θα σας δώσει πίσω μια (ενδεχομένως πολύ ψηλή) ετικέτα με πλάτος 100 (ή λίγο μικρότερο). Ίσως να θέλετε να ορίσετε την ετικέτα σας στο ελάχιστο πλάτος που θέλετε πριν από την αλλαγή μεγέθους.

![Διόρθωση της ευθυγράμμισης της ετικέτας με αλλαγή μεγέθους του πλάτους του πλαισίου][5]

Μερικά άλλα πράγματα που πρέπει να σημειώσετε:

εξαρτάται από τον τρόπο με τον οποίο έχει οριστεί. Το NSLineBreakByTruncatingTail (η προεπιλογή) αγνοείται μετά το sizeToFit, όπως και οι άλλοι δύο τρόποι αποκοπής (κεφαλή και μέση). Η επιλογή NSLineBreakByClipping επίσης αγνοείται. Το NSLineBreakByCharWrapping λειτουργεί ως συνήθως. Το πλάτος του πλαισίου εξακολουθεί να περιορίζεται για να χωρέσει στο δεξιότερο γράμμα.

Εάν η ετικέτα σας περιλαμβάνεται σε ένα nib ή storyboard ως υποπροβολή του view ενός ViewController που χρησιμοποιεί autolayout, τότε η τοποθέτηση της κλήσης sizeToFit στο viewDidLoad δεν θα λειτουργήσει, επειδή το autolayout μεγεθύνει και τοποθετεί τις υποπροβολές μετά την κλήση του viewDidLoad και θα αναιρέσει αμέσως τα αποτελέσματα της κλήσης sizeToFit. Ωστόσο, η κλήση του sizeToFit μέσα από το viewDidLayoutSubviews θα λειτουργήσει.

Σχόλια (13)

Όπως και η παραπάνω απάντηση, αλλά δεν ήταν αρκετά σωστή ή εύκολη για να τη βάλω σε κώδικα, οπότε την καθάρισα λίγο. Προσθέστε αυτή την επέκταση είτε σε δικό της αρχείο .h και .m είτε απλά επικολλήστε την ακριβώς πάνω από την υλοποίηση που σκοπεύετε να χρησιμοποιήσετε:


#pragma mark VerticalAlign
@interface UILabel (VerticalAlign)
- (void)alignTop;
- (void)alignBottom;
@end

@implementation UILabel (VerticalAlign)
- (void)alignTop
{
    CGSize fontSize = [self.text sizeWithFont:self.font];

    double finalHeight = fontSize.height * self.numberOfLines;
    double finalWidth = self.frame.size.width;    //expected width of label

    CGSize theStringSize = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(finalWidth, finalHeight) lineBreakMode:self.lineBreakMode];

    int newLinesToPad = (finalHeight  - theStringSize.height) / fontSize.height;

    for(int i=0; i
Σχόλια (0)

Διάβασα για λίγο τον κώδικα, καθώς και τον κώδικα στη σελίδα εισαγωγής, και διαπίστωσα ότι όλοι προσπαθούν να τροποποιήσουν το μέγεθος του πλαισίου της ετικέτας, έτσι ώστε να μην εμφανίζεται η προεπιλεγμένη κεντρική κάθετη στοίχιση.

Ωστόσο, σε ορισμένες περιπτώσεις θέλουμε η ετικέτα να καταλαμβάνει όλους αυτούς τους χώρους, ακόμα και αν η ετικέτα έχει όντως τόσο κείμενο (π.χ. πολλαπλές σειρές με ίσο ύψος).

Εδώ, χρησιμοποίησα έναν εναλλακτικό τρόπο για να το λύσω, απλά συμπληρώνοντας newlines στο τέλος της ετικέτας (pls σημειώστε ότι στην πραγματικότητα κληρονόμησα το UILabel, αλλά δεν είναι απαραίτητο):

CGSize fontSize = [self.text sizeWithFont:self.font];

finalHeight = fontSize.height * self.numberOfLines;
finalWidth = size.width;    //expected width of label

CGSize theStringSize = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(finalWidth, finalHeight) lineBreakMode:self.lineBreakMode];

int newLinesToPad = (finalHeight  - theStringSize.height) / fontSize.height;

for(int i = 0; i < newLinesToPad; i++)
{
    self.text = [self.text stringByAppendingString:@"\n "];
}
Σχόλια (0)