iOS Recipes - Matt Drance [41]
if ((bottomGap > 0) && self.bottomStretcher) {
if (self.contentOffset.y < 0) {
self.bottomStretcher.hidden = YES;
} else {
self.bottomStretcher.frame = CGRectMake(0, self.contentSize.height,
self.frame.size.width,
bottomGap);
self.bottomStretcher.hidden = NO;
}
} else {
self.bottomStretcher.hidden = YES;
}
More often than not, we can accomplish a two-tone appearance by setting the standard background color, which extends to the bottom automatically, and then setting a custom topColor on our new subclass. We’d set bottomColor only if we wanted a three-tone table with different top, middle, and bottom colors.
We could do a good amount of this work in UIScrollViewDelegate methods on our table view controller, but we’d have to move that code around to every controller we wrote. By overriding ‑layoutSubviews in a subclass of UITableView, we’ve dramatically simplified the process of creating this two-tone effect. We don’t need to remember to implement or connect anything in our controller code—we just create a PRPTwoToneTableView and set our colors, and we can be on our way.
In the next recipe, Recipe 20, Add Border Shadows for Table Views , we take this technique to the next level by automatically adding drop shadows to the borders of a table view.
Recipe 20 Add Border Shadows for Table Views
Problem
You want to add some depth to your table views. How do you get an effect like the one you see in the Clock app, in a way that is both easy and reusable?
Solution
In a number of Apple apps, table views are decorated with border shadows to give some depth and character to their appearance. The most visible examples are the World Clock, Alarm, and Stopwatch tabs in the Clock app. If the tables fill the screen, they look like a plain old table view. But if we scroll them past their top or bottom bounds, we’ll notice a total of four shadows: two on the outer boundaries of the view and two more tracking the top and bottom table cells. We’re going to make a reusable table view that creates this same effect. Figure 23, Table view border shadows shows the look we’re after.
Like in Recipe 19, Produce Two-Tone Table Views , to do the job we’ll override ‑layoutSubviews in a UITableView subclass. This time, though, we’ll write a different layout algorithm to coordinate the shadows in all the appropriate places in the table.
The PRPShadowedTableView is a bit more complicated than the two-tone table we built previously: in that example, we had only two views to manage, and we simply stretched them to fill any gap made while scrolling beyond the top or bottom content bounds. Here, we’re coordinating four subviews representing the shadows, with different conditions affecting each shadow.
Figure 23. Table view border shadows
* * *
Once again we’re inserting subviews to represent the shadows. Why wouldn’t we just set the shadows as part of the standard table header and footer? Well, first of all, doing this would affect the table’s content size. If we set the bottom shadow as the table footer, for example, the table would include room at the bottom for the content shadow so that it was always visible. That isn’t what we want: we want the shadows to have no effect on the actual content size and to be visible only when the respective top or bottom ends of the content are exposed. Second, we want this class to support custom headers and footers without affecting their layout or behavior. Using subviews that are independent of the other content gives us the greatest flexibility and safety.
We start with a common initializer that is called whether the table is created in code or in Interface Builder. This ‑commonInit method installs the four shadow views and performs some additional initialization.
ShadowedTables/Classes/PRPShadowedTableView.m
- (void)commonInit {
[self installShadows];
}
The previously shown screenshot has a table view that doesn’t fill the screen, making the bottom two shadows always visible. In the screenshot, the table is also pulled down past the top of its content,