iOS Recipes - Matt Drance [22]
coreText/Classes/FontsTableViewController.m
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell =
[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier] autorelease];
CGRect frame = CGRectMake(10, 0, self.tableView.frame.size.width,
self.tableView.rowHeight);
PRPAttributedLabel *attLabel =
[[PRPAttributedLabel alloc] initWithFrame:frame];
attLabel.backgroundColor = [UIColor whiteColor];
attLabel.tag = 999;
[cell.contentView addSubview:attLabel];
[attLabel release];
}
PRPAttributedLabel *attLabel = (id)[cell.contentView viewWithTag:999];
attLabel.attributedText =
[self.attributedFontNames objectAtIndex:indexPath.row];
return cell;
}
There are many ways to create attributed strings—often they are built from retrieved XML data—but in this example we need a simple way to build some from normal strings so that we have something to display in our new label.
The illuminatedString method takes an input string and a font to create an attributed string, the first character of which will be set to be slightly larger and also bright red. The remainder of the string will be set to dark gray. We build up the string attribute by attribute, setting the colors and their ranges first and then adding the font with its various sizes.
coreText/Classes/FontsTableViewController.m
- (NSAttributedString *)illuminatedString:(NSString *)text
font:(UIFont *)AtFont{
int len = [text length];
NSMutableAttributedString *mutaString =
[[[NSMutableAttributedString alloc] initWithString:text] autorelease];
[mutaString addAttribute:(NSString *)(kCTForegroundColorAttributeName)
value:(id)[UIColor darkGrayColor].CGColor
range:NSMakeRange(1, len-1)];
[mutaString addAttribute:(NSString *)(kCTForegroundColorAttributeName)
value:(id)[UIColor redColor].CGColor
range:NSMakeRange(0, 1)];
CTFontRef ctFont = CTFontCreateWithName((CFStringRef)AtFont.fontName,
AtFont.pointSize,
NULL);
[mutaString addAttribute:(NSString *)(kCTFontAttributeName)
value:(id)ctFont
range:NSMakeRange(0, 1)];
CTFontRef ctFont2 = CTFontCreateWithName((CFStringRef)AtFont.fontName,
AtFont.pointSize*0.8,
NULL);
[mutaString addAttribute:(NSString *)(kCTFontAttributeName)
value:(id)ctFont2
range:NSMakeRange(1, len-1)];
CFRelease(ctFont);
CFRelease(ctFont2);
return [[mutaString copy] autorelease];
}
The underlinedString method follows a very similar pattern but adds an underline attribute for the first six characters using the kCTUnderlineStyleSingle attribute identifier—again, a little artificial, but it demonstrates the effect quite nicely.
coreText/Classes/FontsTableViewController.m
[mutaString addAttribute:(NSString *)(kCTUnderlineStyleAttributeName)
value:[NSNumber numberWithInt:kCTUnderlineStyleSingle]
range:NSMakeRange(0, 6)];
As it stands, the PRPAttributedLabel class is not as fully featured as the UILabel class. If we wanted to enhance the features, to include better positioning options perhaps, we would need to dig further into Core Text to extract the line and glyph data. With that you could calculate the length and maximum height of the line, in points, and adjust the line positioning to allow for options such as centering or left/right alignment.
Recipe 11 Scroll an Infinite Wall of Album Art
Problem
Scroll views are naturally constrained by the size of the view that is being scrolled. Scroll in any direction, and soon enough you’ll hit the edge of the view and most likely bounce back. Currently, there is no easy way to make the contents of a UIScrollView wrap and still keep the feel of a continuous scroll.
Solution
Instead of hitting an edge, it would be nice to have the view wrap back around, for a more free-flowing experience.