Your browser (Internet Explorer 6) is out of date. It has known security flaws and may not display all features of this and other websites. Learn how to update your browser.
X

iPhone Development: Force UITableView to show only complete cells

Tallymander uses UITableViewCells not only to display data but also to manipulate it. That means that partially-visible cells — that is, those that are cut off at the top or bottom of the view — aren’t terribly useful.

Better, I thought, would be to always ensure that when a partially-visible cell crops up, the UITableViewController will quietly nudge things to be completely visible.

Partially visible cells vs. Fully Visible Cells

In the first image, you can see the only part of the top and bottom cell. In the second image, the cells have been nudged so that everything visible is completely visible. This took a little noodling around with math but it wasn’t hard to do. Put this method into your UITableViewController subclass:

- (void)snapBottomCell
{
	NSInteger cellHeight = 62; //Cells for my view are 62px tall. Sub your own height here
 
	NSInteger offsetOverage = (NSInteger) self.tableView.contentOffset.y % cellHeight;
	//Use the tableview's contentOffset property and the cell height to determine how much is being cut off
 
	if (offsetOverage > 0)
	{
		//If the overage is more than 0, we should figure out what the new offset needs to be
 
		NSInteger newOffset;
 
		if (offsetOverage >= (cellHeight/2))
		{
			newOffset = self.tableView.contentOffset.y + (cellHeight - offsetOverage);
			//If the overage is greater than or equal to half the height of a cell, pull the cell up so it's fully visible
		}
 
		else {
			newOffset = self.tableView.contentOffset.y - offsetOverage;
			//Else, push the cell out of view
		}
 
		//With the new offset determined, animate the movement:
 
		[UIView beginAnimations:nil context:NULL];
		[UIView setAnimationDuration:0.5];
		[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
		[self.tableView setContentOffset:CGPointMake(0, newOffset) animated:NO];
		[UIView commitAnimations];
 
	}
}

You’ll need to implement these two delegate methods as well:

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
	[self snapBottomCell];
}
 
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
	if (decelerate == NO)
	{
		[self snapBottomCell];
	}
}

And that’s it. If more than half of the bottom cell is visible, the cell gets nudged completely into view. If less than half is visible, it’s pushed out of view.

You could change snapBottomCell to accept cellHeight as an argument if you need to accommodate cells with variable heights. You might sort out a particular cell’s height like so:

	NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:CGPointMake(0, (self.tableView.frame.size.height - 1))];
	//Get the index path of the cell currently visible at the bottom edge of the tableview
 
	UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
 
	[self snapBottomCell:cell.frame.size.height];

There are cases where this isn’t useful: long lists whose primary function is selecting data for loading in another view, for example. Still, any time you’re using UITableViewCells to house controls or chunky bits of data, it might be good to ensure that only whole cells are displayed.

Little Things: Don’t Ignore ‘Em

I saw this Bing ad on Facebook:

Bing Ad

See the little movement lines, there on the left? They suggest the weird little dollar coin is moving from left to right. In western cultures (to whom the ad was targeted) left to right progression is associated with forward motion, while right to left progression signals backward motion. This something you’ll see in movies and comic strips if you’re looking for it. Here’s an example we all know and love:

back-to-the-future

The stylized arrow beside the word “Back” is pointing, appropriately, back, via a right-to-left perspective, while all of the letters in that word are also skewed right-to-left. The word “future,” conversely, is skewed left-to-right. It’s an instantly recognizable logo that succeeds by embodying its idea without whacking you over the head with it.

So look again:

Bing Ad

Bing is talking about getting cash back, but illustrating their point by showing cash flowing away. This isn’t the economy to be talking about cash flowing away. I’m not sure that the dissonance this creates registers for most people but when it’s already unlikely that people will engage with your ad unit, the last thing you do is add subconscious resistance.

Yeah, it’s tiny, but the tiny things pile up into the enormous sand dunes that dog every last Microsoft endeavor with needless, unnecessary friction born of poor taste and obliviousness.

For more on this, enjoy a deconstruction of the hideous Bing logo.