UINavigationBarやUIToolbarの上にボタンを表示する際には、UIBarButtonItemを使います。同じような外観のボタンをUIButtonのSubclassとして作りたい時があると思います。UIButton#buttonTypeをUIButtonTypeCustomで作るところまでは想像できると思うのですが、同じような外観にするのは結構面倒です。

でも、ご安心ください。それに相当するものがGitHubにコミットされています。

https://github.com/jessmartin/CoolButtons

CoolButtonというクラスを使うのですが、このクラスはBarButtonのような外観をプログラムで実現しています。任意の色にもできます。

プロジェクトへのインストール

  • CoolButton.mとCoolButton.hをプロジェクトにコピーする
  • QuartzCore.frameworkをプロジェクトに追加

CoolButtonをプログラムで生成する

UIButtonを継承しているので同じ要領で作ります。

CoolButton *coolButton = [CoolButton buttonWithType:UIButtonTypeCustom];
// [[CoolButton alloc] initWithFrame:CGRectMake(8, 8, 100, 37)]でもOK
coolButton.frame = CGRectMake(8, 8, 100, 37);
coolButton.titleLabel.font = [UIFont boldSystemFontOfSize:12];
[coolButton setTitle:@"Cool Button" forState:UIControlStateNormal];
[self.view addSubview:coolButton];

BarButtonそっくりな外観です。

01

ボタンの色替えもできます。

[_coolButton setButtonColor:[UIColor blueColor]];

02

CoolButtonをInterface Builderで配置する

Round Rect Buttonを配置

Identity inspectorでCustom ClassをCoolButtonに変更する

03

Attributes inspectorでTypeをCustomにする

04

あとはFont、Title、Backgroundなどを調整します。

UIBarButtonとして配置

CoolButton *coolButton = [CoolButton buttonWithType:UIButtonTypeCustom];
coolButton.frame = CGRectMake(0, 0, 80, 32);
UIBarButtonItem *barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:coolButton];
[coolButton setTitle:@"Cool" forState:UIControlStateNormal];
self.navigationItem.leftBarButtonItem = barButtonItem;

sizeToFitがうまく機能しない

残念なのはsizeToFitでタイトルの周囲がうまくPaddingされないことです。

05

これはUIButtonTypeがCustomであるときの挙動そのままだからですが・・・

自分はCoolButtonを継承してsizeThatFitsをオーバーライドして対処しています。

- (CGSize)sizeThatFits:(CGSize)size
{
    CGSize newSize = [super sizeThatFits:size];
    newSize.width += 16;
    newSize.height += 16;
    newSize.width = MIN(size.width, newSize.width);
    newSize.height = MIN(size.height, newSize.height);
    return newSize;
}

※ sizeToFitはオーバーライドしないようにドキュメントに書かれているので、しないようにしてください。

システムデフォルトのボタンは嫌だけど、ボタン素材を作るのが面倒な時、仮でも少しマシな外観にしておきたい時にも使えますね。作者さんに感謝です。