Έχω μια UILabel
με χώρο για δύο γραμμές κειμένου. Μερικές φορές, όταν το κείμενο είναι πολύ μικρό, το κείμενο αυτό εμφανίζεται στο κάθετο κέντρο της ετικέτας.
Πώς μπορώ να ευθυγραμμίσω κάθετα το κείμενο ώστε να βρίσκεται πάντα στο επάνω μέρος της UILabel
;
Δεν υπάρχει τρόπος να ορίσετε την κατακόρυφη στοίχιση σε μια UILabel
, αλλά μπορείτε να έχετε το ίδιο αποτέλεσμα αλλάζοντας το πλαίσιο της ετικέτας. Έκανα τις ετικέτες μου πορτοκαλί για να μπορείτε να δείτε καθαρά τι συμβαίνει.
Εδώ είναι ο γρήγορος και εύκολος τρόπος για να το κάνετε αυτό:
[myLabel sizeToFit];
Αν έχετε μια ετικέτα με μεγαλύτερο κείμενο που θα κάνει περισσότερες από μια γραμμές, ορίστε το numberOfLines
σε 0
(το μηδέν εδώ σημαίνει απεριόριστο αριθμό γραμμών).
myLabel.numberOfLines = 0;
[myLabel sizeToFit];
Μακρύτερη έκδοση
Θα φτιάξω την ετικέτα μου σε κώδικα ώστε να μπορείτε να δείτε τι συμβαίνει. Μπορείτε να ρυθμίσετε τα περισσότερα από αυτά και στο 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];
Η ετικέτα εξακολουθεί να έχει μέγεθος με σταθερή πάνω αριστερή γωνία. Μπορείτε να αποθηκεύσετε το αρχικό πλάτος της ετικέτας σε μια μεταβλητή και να το ορίσετε μετά το 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;
Σημειώστε ότι το sizeToFit
θα σεβαστεί το ελάχιστο πλάτος της αρχικής σας ετικέτας. Αν ξεκινήσετε με μια ετικέτα πλάτους 100 και καλέσετε το sizeToFit
σε αυτήν, θα σας δώσει πίσω μια (ενδεχομένως πολύ ψηλή) ετικέτα με πλάτος 100 (ή λίγο μικρότερο). Ίσως να θέλετε να ορίσετε την ετικέτα σας στο ελάχιστο πλάτος που θέλετε πριν από την αλλαγή μεγέθους.
Μερικά άλλα πράγματα που πρέπει να σημειώσετε:
εξαρτάται από τον τρόπο με τον οποίο έχει οριστεί. Το NSLineBreakByTruncatingTail
(η προεπιλογή) αγνοείται μετά το sizeToFit
, όπως και οι άλλοι δύο τρόποι αποκοπής (κεφαλή και μέση). Η επιλογή NSLineBreakByClipping
επίσης αγνοείται. Το NSLineBreakByCharWrapping
λειτουργεί ως συνήθως. Το πλάτος του πλαισίου εξακολουθεί να περιορίζεται για να χωρέσει στο δεξιότερο γράμμα.
<hr>,
Mark Amery έδωσε μια διόρθωση για NIBs και Storyboards που χρησιμοποιούν Auto Layout στα σχόλια:
Εάν η ετικέτα σας περιλαμβάνεται σε ένα nib ή storyboard ως υποπροβολή του
view
ενός ViewController που χρησιμοποιεί autolayout, τότε η τοποθέτηση της κλήσηςsizeToFit
στοviewDidLoad
δεν θα λειτουργήσει, επειδή το autolayout μεγεθύνει και τοποθετεί τις υποπροβολές μετά την κλήση τουviewDidLoad
και θα αναιρέσει αμέσως τα αποτελέσματα της κλήσηςsizeToFit
. Ωστόσο, η κλήση τουsizeToFit
μέσα από τοviewDidLayoutSubviews
θα λειτουργήσει.
<hr>, Η αρχική μου απάντηση (για την υστεροφημία/αναφορά):
Αυτό χρησιμοποιεί τη μέθοδο NSString
sizeWithFont:constrainedToSize:lineBreakMode:
για να υπολογίσει το ύψος του πλαισίου που απαιτείται για να χωρέσει μια συμβολοσειρά, και στη συνέχεια ορίζει την προέλευση και το πλάτος.
Αλλάξτε το μέγεθος του πλαισίου για την ετικέτα χρησιμοποιώντας το κείμενο που θέλετε να εισαγάγετε. Με αυτόν τον τρόπο μπορείτε να φιλοξενήσετε οποιονδήποτε αριθμό γραμμών.
CGSize maximumSize = CGSizeMake(300, 9999);
NSString *dateString = @"The date today is January 1st, 1999";
UIFont *dateFont = [UIFont fontWithName:@"Helvetica" size:14];
CGSize dateStringSize = [dateString sizeWithFont:dateFont
constrainedToSize:maximumSize
lineBreakMode:self.dateLabel.lineBreakMode];
CGRect dateFrame = CGRectMake(10, 10, 300, dateStringSize.height);
self.dateLabel.frame = dateFrame;
Όπως και η παραπάνω απάντηση, αλλά δεν ήταν αρκετά σωστή ή εύκολη για να τη βάλω σε κώδικα, οπότε την καθάρισα λίγο. Προσθέστε αυτή την επέκταση είτε σε δικό της αρχείο .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<= newLinesToPad; i++)
{
self.text = [self.text stringByAppendingString:@" \n"];
}
}
- (void)alignBottom
{
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< newLinesToPad; i++)
{
self.text = [NSString stringWithFormat:@" \n%@",self.text];
}
}
@end
Και στη συνέχεια για να το χρησιμοποιήσετε, βάλτε το κείμενό σας στην ετικέτα και στη συνέχεια καλέστε την κατάλληλη μέθοδο για να το ευθυγραμμίσετε:
[myLabel alignTop];
ή
[myLabel alignBottom];
Διάβασα για λίγο τον κώδικα, καθώς και τον κώδικα στη σελίδα εισαγωγής, και διαπίστωσα ότι όλοι προσπαθούν να τροποποιήσουν το μέγεθος του πλαισίου της ετικέτας, έτσι ώστε να μην εμφανίζεται η προεπιλεγμένη κεντρική κάθετη στοίχιση.
Ωστόσο, σε ορισμένες περιπτώσεις θέλουμε η ετικέτα να καταλαμβάνει όλους αυτούς τους χώρους, ακόμα και αν η ετικέτα έχει όντως τόσο κείμενο (π.χ. πολλαπλές σειρές με ίσο ύψος).
Εδώ, χρησιμοποίησα έναν εναλλακτικό τρόπο για να το λύσω, απλά συμπληρώνοντας 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 "];
}