iPad SDK : Popovers - The Font Size Popover

8/13/2011 3:22:21 PM
To keep the font selector simple, we'll have the size selection as a separate operation, in its own popover. The GUI for the font size selector will consist of a slider, a label showing the slider's value, and a text view showing a preview of the chosen font at the chosen size. As the user operates the slider, the preview immediately reflects the slider's value. Figure 1 shows the GUI in action.
Figure 1. Setting the font size, with live preview

Unlike the font list, the font size popover shouldn't go away as soon as the user touches it—that would be a pretty surprising response from touching a slider. That means that the interaction between DudelViewController and this new popover will be a little simpler than it was for the font list, since the font size popover will never need to be explicitly dismissed in our code. We'll rely on the system to dismiss it when the user clicks outside it.

1. Creating the GUI

In Xcode, use the New File Assistant to make a new Cocoa Touch class. Select UIViewController as its superclass, and configure the check boxes to target iPad and create an .xib file, but to not make it a subclass of UITableViewController. Name the new class FontSizeController.

Start by editing FontSizeController.h, which will contain outlets for each GUI object we need to interact with, an instance variable containing the current chosen font, and an action method for the slider to call. Here's the entire content of the file:

// FontSizeController.h
#import <UIKit/UIKit.h>
@interface FontSizeController : UIViewController {
IBOutlet UITextView *textView;
IBOutlet UISlider *slider;
IBOutlet UILabel *label;
UIFont *font;
@property (retain, nonatomic) UIFont *font;
- (void)takeIntValueFrom:(id)sender;

Now open FontSizeController.xib in Interface Builder. The first thing you'll notice is that the default view contained within is the size of the entire iPad screen. That's way too big for our purposes! It's also showing a black status bar at the top, as if it were a full-screen view.

Select the view, and use the attribute inspector to set the Status Bar value to Unspecified. Then use the size inspector to set its size to 320 by 320. You actually need to do these two steps in that order, since if the Status Bar value is set to Black, Interface Builder wants to treat that view as a full-screen view, and won't let you change its size.


Apple's documentation says that the minimum width for a popover is 320 pixels.

Now use the Library to grab a UITextView, a UISlider, and a UILabel, and put them each into the view, laid out something like what you saw in Figure 6-4. In my version, I've broken up the monotony of the white background by setting the main view's background color to light gray. You can skip this step if you like, or use a different background color.

Next, connect each outlet from File's Owner to one of the GUI objects by control-clicking that icon, dragging to a GUI object, and selecting the appropriate outlet from the list that appears. Then connect the slider's target and action by control-clicking the slider, dragging to File's Owner, and selecting the takeIntValueFrom: method.

Select the UITextView you created earlier. This contains some "Lorem ipsum" text by default, which is fine for our purposes, so leave that bit alone. However, we don't want users interacting with this text view, so use the attribute inspector to turn off the Editable check box, as well as all of the check box options that affect scrolling behavior.

Finally select the slider, and set its minimum and maximum values to 1 and 96, respectively. The GUI is now complete! Save your work, and go back to Xcode.

2. Making It Work

Now it's time for the FontListController implementation, which is shown here in an abbreviated form after deleting extra comments and unneeded overrides from the template:

//  FontSizeController.m
#import "FontSizeController.h"
@implementation FontSizeController
@synthesize font;
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
textView.font = self.font;
NSInteger i = self.font.pointSize;
label.text = [NSString stringWithFormat:@"%d", i];
slider.value = i;

- (BOOL)shouldAutorotateToInterfaceOrientation:
(UIInterfaceOrientation)interfaceOrientation {
// Overridden to allow any orientation.
return YES;
- (void)dealloc {
self.font = nil;
[super dealloc];
- (void)takeIntValueFrom:(id)sender {
NSInteger size = ((UISlider *)sender).value;
self.font = [self.font fontWithSize:size];
textView.font = self.font;
label.text = [NSString stringWithFormat:@"%d", size];

As you can see, this class is quite simple. It basically just responds to the user dragging the slider by modifying the font property and updating the display.

Now all that's left to do is integrate this new class with the view controller. Switch back to DudelViewController.m, where we have a few changes to make. Add this near the top:

#import "FontSizeController.h"

Then update the handleDismissedPopoverController: method like this:

- (void)handleDismissedPopoverCo2ntroller:(UIPopoverController*)popoverController {
if ([popoverController.contentViewController isMemberOfClass:
[FontListController class]]) {
// this is the font list, grab the new selection
FontListController *flc = (FontListController *)
self.font = [UIFont fontWithName:flc.selectedFontName size:self.font.pointSize];
} else if ([popoverController.contentViewController isMemberOfClass:
[FontSizeController class]]) {
FontSizeController *fsc = (FontSizeController *)
self.font = fsc.font;
self.currentPopover = nil;

After that, we just need to fill in the popoverFontSize: method, like this:

- (IBAction)popoverFontSize:(id)sender {
FontSizeController *fsc = [[[FontSizeController alloc] initWithNibName:nil bundle:nil]
fsc.font = self.font;
[self setupNewPopoverControllerForViewController:fsc];
self.currentPopover.popoverContentSize = fsc.view.frame.size;
[self.currentPopover presentPopoverFromBarButtonItem:sender
permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];

The one new thing we're doing in this method is setting the popoverContentSize property on the currentPopover. If we didn't do this, the popup would automatically fill the maximum height of the screen.

With that in place, we're finished with the font size selection popup. Build and run the app, and you should see something like Figure 2. Notice that since this popover knows about the complete UIFont object that is currently set, not just the size, we can display the font preview with the correct font and size.

Figure 2. Setting a font size

Now we have pretty good control over the fonts we're using for the Text tool. This is still far from a word processor or page layout app, but it's a pretty decent start, especially considering how little code we've written!

  •  Beginning Android 3 : The Input Method Framework - Tailored to Your Needs
  •  Beginning Android 3 : Working with Containers - Scrollwork
  •  Mobile Application Security : SMS Security - Protocol Attacks (part 2)
  •  Mobile Application Security : SMS Security - Protocol Attacks (part 1)
  •  Mobile Application Security : SMS Security - Overview of Short Message Service
  •  iPad SDK : Popovers - The Font Name Popover (part 2)
  •  iPad SDK : Popovers - The Font Name Popover (part 1)
  •  Beginning Android 3 : Working with Containers - Tabula Rasa
  •  Beginning Android 3 : Working with Containers - LinearLayout Example & The Box Model
  •  iPhone Application Development : Reading and Writing User Defaults (part 2) - Implementing System Settings
  •  iPhone Application Development : Reading and Writing User Defaults (part 1) - Creating Implicit Preferences
  •  - Mobile Application Security : SMS Security - Overview of Short Message Service
  •  - Mobile Application Security : Bluetooth Security - Bluetooth Security Features
  •  Integrating Your Application with Windows Phone 7
  •  Introducing Windows Phone 7 Photo Features (part 2) - Using a Chooser to Open Photos & Saving Photos to the Phone
  •  Introducing Windows Phone 7 Photo Features (part 1) - Using a Chooser to Take Photos
  •  Mobile Application Security : Bluetooth Security - Bluetooth Technical Architecture
  •  Mobile Application Security : Bluetooth Security - Overview of the Technology
  •  Windows Phone 7 Development : Push Notifications - Implementing Cloud Service to Track Push Notifications
  •  Windows Phone 7 Development : Push Notifications - Implementing Raw Notifications
    Top 10
    Nikon 1 J2 With Stylish Design And Dependable Image And Video Quality
    Canon Powershot D20 - Super-Durable Waterproof Camera
    Fujifilm Finepix F800EXR – Another Excellent EXR
    Sony NEX-6 – The Best Compact Camera
    Teufel Cubycon 2 – An Excellent All-In-One For Films
    Dell S2740L - A Beautifully Crafted 27-inch IPS Monitor
    Philips 55PFL6007T With Fantastic Picture Quality
    Philips Gioco 278G4 – An Excellent 27-inch Screen
    Sony VPL-HW50ES – Sony’s Best Home Cinema Projector
    Windows Vista : Installing and Running Applications - Launching Applications
    Most View
    Bamboo Splash - Powerful Specs And Friendly Interface
    Powered By Windows (Part 2) - Toshiba Satellite U840 Series, Philips E248C3 MODA Lightframe Monitor & HP Envy Spectre 14
    MSI X79A-GD65 8D - Power without the Cost
    Canon EOS M With Wonderful Touchscreen Interface (Part 1)
    Windows Server 2003 : Building an Active Directory Structure (part 1) - The First Domain
    Personalize Your iPhone Case
    Speed ​​up browsing with a faster DNS
    Using and Configuring Public Folder Sharing
    Extending the Real-Time Communications Functionality of Exchange Server 2007 : Installing OCS 2007 (part 1)
    Google, privacy & you (Part 1)
    iPhone Application Development : Making Multivalue Choices with Pickers - Understanding Pickers
    Microsoft Surface With Windows RT - Truly A Unique Tablet
    Network Configuration & Troubleshooting (Part 1)
    Panasonic Lumix GH3 – The Fastest Touchscreen-Camera (Part 2)
    Programming Microsoft SQL Server 2005 : FOR XML Commands (part 3) - OPENXML Enhancements in SQL Server 2005
    Exchange Server 2010 : Track Exchange Performance (part 2) - Test the Performance Limitations in a Lab
    Extra Network Hardware Round-Up (Part 2) - NAS Drives, Media Center Extenders & Games Consoles
    Windows Server 2003 : Planning a Host Name Resolution Strategy - Understanding Name Resolution Requirements
    Google’s Data Liberation Front (Part 2)
    Datacolor SpyderLensCal (Part 1)