Changing the Navigation Bar: MFMailComposeViewController

Changing the Navigation Bar: MFMailComposeViewController

The iPhone 3.0 SDK introduced a number of cool new controllers, one of which was the MFMailComposeViewController class.

And although – in and of itself – it does so much, like much of what we run into in this developer life, it leaves some things greatly to be desired.

Like, “why in the heck does it ** have ** to put the subject line in the navigation bar as a title? Don’t they ** know ** I have a cool custom nav bar that they’re totally puking over?!?!?!

Don’t fret. There is a solution.

First, you’ll need to implement the following delegate in the .h file of the controller where you are implementing the mail composer:

MFMailComposeViewControllerDelegate

Next, you’ll need to implement some sort of event handler. Here’s mine:

-(IBAction)doEmail:(id)id {
if ([MFMailComposeViewController canSendMail]) {

  MFMailComposeViewController *controller = [[MFMailComposeViewController alloc] init];

  controller.mailComposeDelegate = self;
  [controller setSubject:@"My Subject"];
  [controller setMessageBody:@"My Body" isHTML:YES];

  [self presentModalViewController:controller animated:YES];

  [[controller navigationBar] setTintColor:[UIColor greenColor]];
  UIImage *image = [UIImage imageNamed: @"custom_nav_background.png"];
  UIImageView * iv = [[UIImageView alloc] initWithFrame:CGRectMake(0,0,320,42)];
  iv.image = image;
  iv.contentMode = UIViewContentModeCenter;
  [[[controller viewControllers] lastObject] navigationItem].titleView = iv;
  [[controller navigationBar] sendSubviewToBack:iv];
  [iv release];
 
  [controller release];
  }
else {
  UIAlertView* myAlert = [[UIAlertView alloc] initWithTitle:@"My App" message:[NSString stringWithFormat:@"You cannot send email at this time."] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
  [myAlert show];
  [myAlert release];
  }
}

Finally, you’ll need to implement a method to dismiss the email composer after you cancel or send.

// Dismiss email composer UI on cancel / send
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error {
  [self becomeFirstResponder];
  [self dismissModalViewControllerAnimated:YES];
}

The bits that take care of the custom navigation bar (and incidentally, hiding the subject line title Apple insists on fobbing off on you) are in bold in the code above.

There are a few interesting details to note:

  [[controller navigationBar] setTintColor:[UIColor greenColor]];

Will tint the Cancel and Send buttons to whatever color you like; in this example, I chose green. Use whatever you like here.

  UIImage *image = [UIImage imageNamed: @"custom_nav_background.png"];
  UIImageView * iv = [[UIImageView alloc] initWithFrame:CGRectMake(0,0,320,42)];
  iv.image = image;
  iv.contentMode = UIViewContentModeCenter;
  [[[controller viewControllers] lastObject] navigationItem].titleView = iv;
  [[controller navigationBar] sendSubviewToBack:iv];
  [iv release];

The code above loads an navigation bar image (320 x 42 pixels for iPhone 2G, 3G, and 3Gs; 640 x 84 pixels for retina display), and sets the titleView on the MFMailComposerViewController navigation bar to the UIImageView I constructed with my custom navigation bar background.

And last but definitely not least, we must send the custom titleView to the back so that we can “see” the Cancel and Send buttons.

The subject line will now no longer appear in the title bar – which is why I did this in the first place. It was totally jamming my chi.

Give it a try. I’d be interested in your feedback on this solution.

11 thoughts on “Changing the Navigation Bar: MFMailComposeViewController

  1. [[[controller viewControllers] lastObject] navigationItem].titleView = iv;
    can be written as
    controller.topViewController.navigationItem.titleView = iv;

    Like

  2. Do you have a solution for iOS 5? I can no longer get the default title “new message” on the nav bar to go away. My custom background image shows, but I have a logo in the center and “new message” is displaying over top of it

    Like

    1. You might be able to by walking the chain of subviews… but my guess would be that Apple would frown upon changing the buttons on a standard view controller.

      Like

  3. Can you or anyone comment on if changes like this would be accepted by Apple? I’ve seen various comments going both ways.
    Thanks

    Like

Leave a comment