iPhone Development - Another question on resizng UILabel & custom UITableViewCell
-
19-09-2019 - |
Question
I've used following function in some of my projects, but recently I've created a small example which suggest that it's not reliable (at least in some situations):
[NSString sizeWithFont:font constrainedToSize:size]
[NSString sizeWithFont:font constrainedToSize:size lineBreakMode:lineBreak]
I created a custom UITableViewCell class to achieve the results as seen in iPhone's Photo Album application e.g. Picture, with Album Name, and count of Pictures in the album. I used the above function to adjust my detail text (for count). Here's the code:
Interface File:
#import <UIKit/UIKit.h>
@interface CustomValue2Cell : UITableViewCell {
UIImageView *cellImage;
UILabel *cellTextLabel;
UILabel *cellDetailTextLabel;
}
@property (nonatomic, retain) UIImageView *cellImage;
@property (nonatomic, retain) UILabel *cellTextLabel;
@property (nonatomic, retain) UILabel *cellDetailTextLabel;
- (void)setCellImage:(UIImage *)image withText:(NSString *)text andDetail:(NSString *)detail;
- (CGSize)getSizeOfText:(NSString *)text withFont:(UIFont *)font;
@end
Implementation File:
#import "CustomValue2Cell.h"
@implementation CustomValue2Cell
@synthesize cellImage;
@synthesize cellTextLabel;
@synthesize cellDetailTextLabel;
// Coordinate positions of Image, Text Label, and Detail Text Label
# define kImageXPosition 3
# define kImageYPosition 3
# define kImageWidth 37.0
# define kImageHeight 37.0
# define kTextXPosition 55
# define kTextYPosition 10
# define kTextWidth 200
# define kTextHeight 22
# define kDetailXPosition 55
# define kDetailYPosition 10
# define kDetailWidth 40
# define kDetailHeight 22
// Displacement value for Text Label with Detail Text Label
// Displacement value of 10-15 works with non-bold font
# define kCellSubviewDisplacement 20
// Label Font Size for Text Label and Detail Text Label
# define kTextLabelFontSize 18
# define kDetailLabelFontSize 16
- (id)initWithFrame:(CGRect)frame reuseIdentifier:(NSString *)reuseIdentifier {
if (self = [super initWithFrame:frame reuseIdentifier:reuseIdentifier]) {
// Color and font for the main label
UIColor *textLabelColor = [UIColor blackColor];
UIFont *textLabelFont = [UIFont systemFontOfSize:kTextLabelFontSize];
// Color and font for the detail label
UIColor *detailTextColor = [UIColor darkGrayColor];
UIFont *detailTextFont = [UIFont systemFontOfSize:kDetailLabelFontSize];
// Highligted row color
UIColor *highlightedTextColor = [UIColor whiteColor];
// Define boundary of the cell contents
CGRect rect;
// Set properties of Image Thumbnail
rect = CGRectMake(kImageXPosition, kImageYPosition, kImageWidth, kImageHeight);
cellImage = [[UIImageView alloc] initWithFrame:rect];
// Set properties of Name
rect = CGRectMake(kTextXPosition, kTextYPosition, kTextWidth, kTextHeight);
cellTextLabel = [[UILabel alloc] initWithFrame:rect];
[cellTextLabel setFont:textLabelFont];
[cellTextLabel setTextColor:textLabelColor];
[cellTextLabel setHighlightedTextColor:highlightedTextColor];
// Set properties of Value
rect = CGRectMake(kDetailXPosition, kDetailYPosition, kDetailWidth, kDetailHeight);
cellDetailTextLabel = [[UILabel alloc] initWithFrame:rect];
[cellDetailTextLabel setFont:detailTextFont];
[cellDetailTextLabel setTextColor:detailTextColor];
[cellDetailTextLabel setHighlightedTextColor:highlightedTextColor];
// Put Image, Name, and Value in Content View
[[self contentView] addSubview:cellImage];
[[self contentView] addSubview:cellTextLabel];
[[self contentView] addSubview:cellDetailTextLabel];
//Set cell selection style (Blue)
self.selectionStyle = UITableViewCellSelectionStyleBlue;
}
return self;
}
- (void)setCellImage:(UIImage *)image withText:(NSString *)text andDetail:(NSString *)detail {
cellImage.image = image;
cellTextLabel.text = text;
cellDetailTextLabel.text = detail;
// Get an estimated size of text in the label,
// which will be used to estimate the position of detail label
UIFont *textLabelFont = [UIFont systemFontOfSize:kTextLabelFontSize];
CGSize size = [self getSizeOfText:text withFont:textLabelFont];
// Re-set the frame of detail view
CGRect frame = CGRectMake(kDetailXPosition, kDetailYPosition, kDetailWidth, kDetailHeight);
frame.origin.x = frame.origin.x + size.width + kCellSubviewDisplacement;
[cellDetailTextLabel setFrame:frame];
}
- (CGSize)getSizeOfText:(NSString *)text withFont:(UIFont *)font {
return [text sizeWithFont:font constrainedToSize:CGSizeMake(kTextWidth, kTextHeight)];
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (void)dealloc {
[cellImage release];
[cellTextLabel release];
[cellDetailTextLabel release];
[super dealloc];
}
@end
To test my custom class i prepared a list of fonts and displayed them in my table View. Code to get list of available fonts:
fontFamily = [[NSMutableArray alloc] initWithArray:[UIFont familyNames]];
fonts = [[NSMutableArray alloc] init];
for(NSUInteger i=0; i<[fontFamily count]; i++) {
NSString *familyName = [fontFamily objectAtIndex:i];
NSArray *array = [UIFont fontNamesForFamilyName:familyName];
[fonts addObjectsFromArray:array];
}
Here's the code to return the cells:
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
CGRect rect = CGRectMake(0.0, 0.0, 320.0, 50.0);
CustomValue2Cell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[CustomValue2Cell alloc] initWithFrame:rect reuseIdentifier:CellIdentifier] autorelease];
}
NSString *font = [fonts objectAtIndex:indexPath.row];
NSString *detail = [NSString stringWithFormat:@"%d", [[fonts objectAtIndex:indexPath.row] length]];
[cell setCellImage:[UIImage imageNamed:@"Pointy.gif"] withText:font andDetail:detail];
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator]
return cell;
}
Result: Text Label and Detail Text Label are overlapping for some values. e.g. "CouierNewPS-BoldMT" and "25" overlap each other, and in some other cases, they are not overlapping but they are very close.
Question: Is their a better alternative to -sizeWithFont function? Or, am i doing something very stupid to mess things up?
Sorry for a long post. Any help is appreciated. Thanking in anticipation.
Solution
Well, you never really say exactly what the problem IS. Does it return a size too large, too small, all on one line, or something else entirely?
When I do string sizing, I use
- (CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size lineBreakMode:(UILineBreakMode)lineBreakMode
and specify UILineBreakModeWordWrap
for the line break mode. I'm not sure if this ends up returning essentially the same value or not, but I've found it to work for me.
Reference : NSString UIKit Additions Reference Class Reference
OTHER TIPS
CGSize size, constrainedSize;
constrianedSize.width = MAXFLOAT; constrainedSize.height = MAXFLOAT;
size = [text sizewithFont:systemFontofSize:14 constrainedToSize:constrinedSize lineBreakMode];
returned constrainedSize should have correct width/height of text.
I had a similar problem with this function and after debugging it for lot of times, I finally figured that if you pass the width less than the label width to the parameter constratainedToSize, it works in all the cases.
Please try the below
- (CGSize)getSizeOfText:(NSString *)text withFont:(UIFont *)font {
return [text sizeWithFont:font constrainedToSize:CGSizeMake(kTextWidth - 10, kTextHeight)];
}
Also use UILineBreakModeWordWrap as a value for UILineBreakMode