Showing posts with label UITableViewCell. Show all posts
Showing posts with label UITableViewCell. Show all posts

Sunday, March 27, 2011

Hide UITableView Empty Cell Separator Lines

Plain UITableView displays cell separator lines, when table is empty or has only a few real cells. This is the default behaviour - and it is good. You should not change it.

But sometimes it looks a bit too weird. When your cells have different heights, all empty cells following the last real one will use last cell's height. If this changes at every table refresh, the "jumping" empty cells start annoying users. Or at least developers.

Monday, February 7, 2011

UITableView with Custom Cell Height

I'm writing an application, where startup view contains UITableView - which seemed pretty slow. Basic version is not too bad, but when using a custom UITableViewCell created from XIB, it became totally unusable.

Time to debug whether Interface Builder's XIB makes things slow!

Thursday, November 11, 2010

How to Define UITableViewCell reuseIdentifier for loadNibNamed

When you create UITableViewCells, it's important to use reuseIdentified. This lets iOS recycle your table cells, thus improving performance and minimizing memory use. Using it is pretty simple:

static NSString *idCell = @"MyCellId";
cell = (UITableViewCell *)[aTableView dequeueReusableCellWithIdentifier:idCell];
Try to reuse an already existing, but not currently used, cell created earlier with given identifier "MyCellId". If such isn't found, create a new one:
if (cell == nil)
{
    static NSString *nibcell = @"MyCell";
    NSArray *nib = [[NSBundle mainBundle] loadNibNamed:nibCell owner:self options:nil];
    cell = (UITableViewCell *)[nib objectAtIndex:0];
}
This code requires a separate stand-alone XIB, which contains nothing but your UITableViewCell. But how do you define the reuseIdenfier? That property is read-only and created when table cell is created.
reuseIdentifier
A string used to identify a cell that is reusable. (read-only)
@property(nonatomic, readonly, copy) NSString *reuseIdentifier
Open your XIB in Interface Builder, select UITableViewCell object, open "Table View Cell Attributes" (press command-1) and write your hardcoded magical string "MyCellId" into "Identifier" field. Use the same string in your code as reuseIdentifier.

Warning: you should NEVER access objects inside XIB (NIB) by magical index into array! Apple might change "something" in next Xcode release and thus break your code. You should use IBOutlets. You have been warned.

...yes, this is one of those sad "don't do as I do, but as I tell you to" cases...

Wednesday, October 20, 2010

How to Make Round Corners for UITableViewCell

Sometimes you need round border around one or more UITableViewCell. Or maybe a button look-a-like without going through the trouble of actually making one. Here's a quick way:

First of all, you MUST include QuartzCore header, else meet some interesting error notes:
#import <QuartzCore/QuartzCore.h>
Then add this code after your cell initialization routine, usually at cellForRowAtIndexPath:
CALayer *layer = cell.layer;
layer.borderColor = [[UIColor blueColor] CGColor];
layer.borderWidth = 3.0f;
layer.cornerRadius = 20.0f;
Like many things in iOS SDK, you get to a certain point with relative ease - and this is about it. If you want to have more control over your "bubble button" you either dig deep into Quartz sample code or implement something which looks same in a completely different way.

For example I replaced this (got a bit further with carefully positioned UIViews inside UITableViewCell) with hardcoded bitmaps and scaling them nicely.

Wednesday, October 6, 2010

How to Float an Icon after UILabel

Want to place a floating icon right after a variable lenght text string - using Interface Builder? Wonderful helper that IB tool or so I thought...

First create a UITableViewCell template with IB, put there a fixed lenght UILabel followed by a UIImageView. No problems, their values are easy to setup at cellForRowAtIndexPath with view tag id numbers:
UILabel *label = nil;
UIImageView *image = nil;
CGRect frame;

// Title
label = (UILabel *)[cell viewWithTag:1];
label.text = @"Title text";
But how to "float" that image right after text string? UILabel is fixed sized, so that won't help. Have to check the size of label.text instead:
// Icon
image = (UIImageView *)[cell viewWithTag:10];
image.image = [UIImage imageNamed:@"logo.png"];

// Icon positioning
frame = image.frame;
CGSize f = [label sizeThatFits:label.frame.size];
frame.origin.x = label.frame.origin.x + f.width + 4;
image.frame = frame;
That's it, very simple! Just beware that your tag numbers MUST be unique.

I had a problem that Interface Builder wanted to set UITableViewCell tag same as my image tag. No errors, no warnings, no indications of problem - except that I couldn't get my image frame no matter how much I banged head into brickwall! Removing tag didn't help, it just automagically came back. Ouch!

Monday, February 1, 2010

How to Disable UITableCell Selection

Sometimes you just want to show a list (UITableView) without selecting any row. By default a table (cell) is selectable, so how to disable it. What worked for me was defining each cell separately as non-selectable:

cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
...
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}

You could also try controlling the whole table, but it didn't work for me:

- (void)viewDidLoad
{
// Prevent message cell selection
self.chatTableView.allowsSelection = NO;
// HOX: not iPhone 2.2.1 compatible --> crash
[super viewDidLoad];
}

This is also supposed to work, but I recall I still got a selection flash:


- (NSIndexPath *) tableView:(UITableView *)_tableView willSelectRowAtIndexPath:(NSIndexPath *)_indexPath
{
// Return nil if you don't want the row selected.
// Hox: interferes with didSelectRowAtIndexPath
return nil;
}