rakuishi.com

[iOS SDK] UINavigationBar の戻るボタンの見た目をカスタマイズする

UINavigationBar で、一個前の階層に戻る「戻るボタン」の外見をカスタマイズする際に、UIAppearance が使えそうで使えなかったので、独自に実装してみました。これよりもスマートな方法を知っていたら誰か教えてください。

UINavigationBar の戻るボタンの見た目をカスタマイズする

カスタムされた戻るボタンを取り扱いやすいように、カテゴリによるクラス拡張を利用します。ここでは、「UIBarButtonItem+DesignedButton」というヘッダファイルとメソッドファイルを用意します。

下図(backbtn@2x.png)のような背景画像を用意しました。これに加えて、押された場合の背景画像(backbtn_hl)も用意しておきます。

UIBarButtonItem+DesignedButton.h

#import <UIKit/UIKit.h>

@interface UIBarButtonItem (DesignedButton)

- (UIBarButtonItem *)designedBackBarButtonItemWithTitle:(NSString *)title target:(id)target action:(SEL)selector;

@end

UIBarButtonItem+DesignedButton.m

#import "UIBarButtonItem+DesignedButton.h"

@implementation UIBarButtonItem (DesignedButton)

- (UIBarButtonItem *)designedBackBarButtonItemWithTitle:(NSString *)title target:(id)target action:(SEL)selector
{
    // 通常時の画像と押された時の画像を用意する
    UIImage *image = [UIImage imageNamed:@"backbtn.png"];
    UIImage *highlightedImage = [UIImage imageNamed:@"backbtn_hl.png"];
    // 左右 17px 固定で引き伸ばして利用する
    image = [image resizableImageWithCapInsets:UIEdgeInsetsMake(0, 17.f, 0, 17.f)];
    highlightedImage = [highlightedImage resizableImageWithCapInsets:UIEdgeInsetsMake(0, 17.f, 0, 17.f)];

    // 表示する文字に応じてボタンサイズを変更する
    UIFont *font = [UIFont boldSystemFontOfSize:12.f];
    CGSize textSize = [title sizeWithFont:font];
    CGSize buttonSize = CGSizeMake(textSize.width + 24.f, image.size.height);

    // ボタンを用意する
    UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0.f, 0.f, buttonSize.width, buttonSize.height)];
    [button addTarget:target action:selector forControlEvents:UIControlEventTouchUpInside];

    [button setBackgroundImage:image forState:UIControlStateNormal];
    [button setBackgroundImage:highlightedImage forState:UIControlStateHighlighted];

    // ラベルを用意する
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(4.f, 0.f, buttonSize.width, buttonSize.height)];
    label.text = title;
    label.textColor = [UIColor whiteColor];
    label.font = font;
    label.shadowColor = [UIColor colorWithWhite:0.0 alpha:0.2];
    label.shadowOffset = CGSizeMake(0.f, 1.f);
    label.backgroundColor = [UIColor clearColor];
    label.textAlignment = UITextAlignmentCenter;
    [button addSubview:label];

    return [[UIBarButtonItem alloc] initWithCustomView:button];
}

@end

これで準備は終わりです。次はこれを実装する方法を示します。

実装してみる

先程、実装したファイルを import します。そして、カスタムされた戻るボタンを利用する時に、次のようなコードを書けば OK です。

    UIBarButtonItem *backButton = [[UIBarButtonItem alloc] designedBackBarButtonItemWithTitle:@"戻る" target:self action:@selector(backButtonTapped)];
    self.navigationItem.leftBarButtonItem = backButton;

ここで注意しておきたいのが、あくまで UIBarButtonItem を戻るボタンに偽装しているので、このままでは一階層前のビューに戻らない点です。なので、戻るために、次のメソッドを読ませます。

- (void)backButtonTapped
{
    [self.navigationController popViewControllerAnimated:YES];
}

もっとスマートな方法があるとは思いますが、とりあえずこんな感じで実装しています。