iPhone: SMS balloon cell
Here is a small description about how to implement SMS-like ballon cell with UITableViewCell & UITableView for iPhone SDK. People often ask about it & though googling is helpful, I just wanted to put it together to save some time. The code is based on the ihonedevsdk.com forum thread. What are we going to accomplish is displayed on the image below:
![]() |
| Альбом: Tolik aka AcidumIrae |
You can find colored bubbles at the George Zhu's BLOG. Just flip canvas in any graphics editor for the odd row balloons.
First we need to create a custom UITableViewCell with UITextView in it. The UITextView will hold our "message". Custom ThreadSCell cell interface:
@interface ThreadSCell : UITableViewCell {
UITextView *msgText;
}
@property (nonatomic,assign) UITextView *msgText;
@end
We don't want it to be editable or have scrolling, also will set background to be transparent. Custom ThreadSCell cell implementation:
#import "ThreadSCell.h"
@implementation ThreadSCell
@synthesize msgText;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
// Initialization code
msgText = [[UITextView alloc] init];
msgText.backgroundColor = [UIColor clearColor];
msgText.editable = NO;
msgText.scrollEnabled = NO;
[msgText sizeToFit];
[self.contentView addSubview:msgText];
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
}
- (void)dealloc {
[super dealloc];
}
@end
Next we need the UITableViewController or the UIViewController with UITableView delegates. Let's do a simple test. Test view controller interface:
@interface testaaaViewController : UIViewController
{
IBOutlet UITableView *tblView;
NSMutableArray *myMessages;
}
@end
Create some data in the test view controller (you can put it in viewDidLoad):
myMessages = [[NSMutableArray alloc] initWithCapacity:0];
[myMessages addObject:
[NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:@"1 apr. 2010 13:01",@"So why do they call him \"The Joker\"?",nil]
forKeys:[NSArray arrayWithObjects:@"msgDate",@"msgBody",nil]]];
[myMessages addObject:
[NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:@"1 apr. 2010 13:03",@"I heard he wears make-up.",nil]
forKeys:[NSArray arrayWithObjects:@"msgDate",@"msgBody",nil]]];
[myMessages addObject:
[NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:@"1 apr. 2010 13:07",@"Make-up?",nil]
forKeys:[NSArray arrayWithObjects:@"msgDate",@"msgBody",nil]]];
[myMessages addObject:
[NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:@"1 apr. 2010 13:11",@"Yeah, to scare people.\n You know, war paint. ",nil]
forKeys:[NSArray arrayWithObjects:@"msgDate",@"msgBody",nil]]];
Now is the tricky part - we need to calculate cell height:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
// Calculate
CGSize textSize = { 260.0, 20000.0 }; // width and height of text area
NSMutableDictionary *dict = [myMessages objectAtIndex:indexPath.section];
NSString *aMsg = [dict objectForKey:@"msgBody"];
CGSize size = [aMsg sizeWithFont:[UIFont systemFontOfSize:13.0] constrainedToSize:textSize lineBreakMode:UILineBreakModeWordWrap];
size.height += 5;
CGFloat height = size.height<36?36:size.height;
return height;
}
And finally layout our cell:
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"MsgListCell";
ThreadSCell *cell = (ThreadSCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// If no cell is available, create a new one using the given identifier
if (cell == nil) {
cell = [[[ThreadSCell alloc] initWithFrame:CGRectMake(0,0,0,0) reuseIdentifier:CellIdentifier] autorelease];
cell.accessoryType = UITableViewCellAccessoryNone;
}
NSMutableDictionary *tempMsg = [myMessages objectAtIndex:indexPath.section];
CGFloat result = 20.0;
CGSize textSize = { 260.0, 20000.0 }; // width and height of text area
NSMutableDictionary *dict = [myMessages objectAtIndex:indexPath.section];
NSString *aMsg = [[dict objectForKey:@"msgBody"] stringByReplacingOccurrencesOfString:@"\n" withString:@" "];
CGSize size = [aMsg sizeWithFont:[UIFont systemFontOfSize:13.0] constrainedToSize:textSize lineBreakMode:UILineBreakModeWordWrap];
result = MAX(size.height - 5.0, 30.0);
// Set the cell properities
[cell.msgText setText:[tempMsg objectForKey:@"msgBody"]];
[tblView setSeparatorStyle:UITableViewCellSeparatorStyleNone];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
[cell setFrame:CGRectMake(0, 0, size.width, size.height)];
if ( indexPath.section % 2 == 0 ) {
[cell.msgText setFrame:CGRectMake(20.0, 0.0, size.width, result)];
UIImage* balloon = [[UIImage imageNamed:@"grey.png"] stretchableImageWithLeftCapWidth:24 topCapHeight:15];
UIImageView *newImage = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, size.width+35, result+10)];
UIView *newView =[[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, cell.frame.size.width, cell.frame.size.height)];
[newImage setImage:balloon];
[newView addSubview:newImage];
[cell setBackgroundView:newView];
}
else
{
[cell.msgText setFrame:CGRectMake(280.0-size.width, 0.0, size.width, result)];
UIImage* balloon = [[UIImage imageNamed:@"green.png"] stretchableImageWithLeftCapWidth:24 topCapHeight:15];
UIImageView *newImage = [[UIImageView alloc] initWithFrame:CGRectMake(270.0-size.width, 0.0, size.width+35, result+10)];
UIView *newView =[[UIView alloc] initWithFrame:CGRectMake(0, 0.0, cell.frame.size.width, cell.frame.size.height)];
[newImage setImage:balloon];
[newView addSubview:newImage];
[cell setBackgroundView:newView];
}
return cell;
}
That's pretty all about it :)
You can download the whole XCode project from this page.


0 comments:
Post a Comment