前回の続き

今回はUINavigationControllerのNavigationBarとToolbarにボタンを配置する方法を説明します。

サンプル: https://github.com/stack3/UINavigationControllerSamples

サンプルを起動してBarButtonを選択すると以下の画面(STBarButtonViewController)が表示されます。

01

NavigationBar右上の書き込みボタンを押すと、以下の様な画面(STMessageViewController)が表示されます。

02

NavigationBarにボタンを表示する

NavigationBarの右上の書き込みボタン。

08

これはSTBarButtonViewControllerのviewDidLoadで以下のようにして表示しています。

self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] 
  initWithBarButtonSystemItem:UIBarButtonSystemItemCompose
  target:self
  action:@selector(didTapMessageButton)];

UIViewController#rightBarButtonItemにUIBarButtonItemオブジェクトを生成して代入しています。

左側に表示したい時はUIViewController#leftBarButtonItemに設定します。しかし戻るボタンと一緒に表示することはできません。leftBarButtonItemを設定すると戻るボタンが消えてしまいます。leftBarButtonItemは基本モーダル表示のときに使います。これは後述します。

注意すべきなのは、UIBarButtonItemはUIViewではないことです。ボタンを表示するのはUINavigationController#navigationBarの上です。navigationBarへのボタン配置はUINavigationControllerが適切なタイミングで行います。画面遷移する時、スライドするアニメーションと共にボタンが切り替わりますが、その表示切替のタイミングなどは我々が考慮する必要はありません。UINavigationControllerが内包するViewControllerのrightBarButtonItem/leftBarButtonItemを見て適切なタイミングで切り替えてくれます。

UIBarButtonItem#initWithBarButtonSystemItem:target:actionの引数は以下のとおりです。

  • BarButtonSystemItem: 定義されたボタン。UIBarButtonSystemItem***(enum値)
  • target: 押された時のactionを受け取るクラス。通常self(ViewController)
  • action: 押された時に呼ばれるメソッド

UIBarButtonSystemItemはシステムで用意されたものがenumで定義されています。以下はその一部です。

UIBarButtonSystemItemAdd 09-plus プラスアイコン
UIBarButtonSystemItemTrash 09-3 ゴミ箱アイコン
UIBarButtonSystemItemDone 09-done Done(完了)ボタン。背景が青色になる
UIBarButtonSystemItemFlexibleSpace 隣り合うBarButtonItemの間に出来る限り広い空白を入れる
UIBarButtonSystemItemFixedSpace UIBarButtonItem#widthで指定された幅の空白を入れる

UIBarButtonSystemItemFlexibleSpace、UIBarButtonSystemItemFixedSpaceは、基本的にToolbarで使うものです。これらは後で説明します。

他にも色々ありますが、詳しくは公式ドキュメントを見てください。

ボタンのアイコンに任意の画像を使う場合

ここで定義されたもの以外のアイコンを表示したいことも当然あるので、その時はPNG画像を用意してそれをinitWithImage:style:target:action:メソッドで指定します。

UIImage *image = [UIImage imageNamed:@"tweet.png"];
UIBarButtonItem *tweetButton = [[UIBarButtonItem alloc] initWithImage:image
                                                                style:UIBarButtonItemStyleBordered
                                                               target:self
                                                               action:@selector(didTapTweetButton)];

アイコン画像が大きすぎる場合は自動的に縮小されます。基本的にはアイコンサイズは20x20pxに収まるようになり、ボタンもそれに応じた大きさになります。

その他、UIBarButtonItemでよく使うプロパティ

  • enabled – NOにすると使用不可能にする
  • style – ボタンの外観を設定。UIBarButtonItemStyleBordered(背景と枠つき)、UIBarButtonItemStyleBordered(アイコンのみ)、UIBarButtonItemStyleDone(青背景、枠つき)
  • tintColor – ボタンの色を設定。

NavigationBarの左ボタンとDoneボタン

STMessageViewControllerのNavigationBarのボタン。

07

これはSTMessageViewController#viewDidLoadで以下のように左ボタンと右ボタンを設定しています。

self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Close"
                                                                         style:UIBarButtonItemStyleBordered
                                                                        target:self
                                                                        action:@selector(didTapCloseButton)];

self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone
                                                                                       target:self
                                                                                       action:@selector(didTapDoneButton)];

STMessageViewControllerはpresentViewController:animatedによってモーダルで開かれているので、戻るボタンはありません。よってleftBarButtonItemにCloseボタンを設定しています。右ボタンはDoneボタンにしています。ちょっとメッセージ投稿画面ぽいですね。

※ 「Done」は日本語環境では「完了」と表示されます。

Toolbarにボタンを表示する

STBarButtonViewControllerのviewDidLoadで以下のようにToolbarのボタンを設定しています。

// 左端のプラスボタン
UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd
                                                                           target:self
                                                                           action:@selector(didTapAddButton)];
// 中心のテキストボタン
UIBarButtonItem *textButton = [[UIBarButtonItem alloc] initWithTitle:@"Text"
                                                               style:UIBarButtonItemStylePlain
                                                              target:self
                                                              action:@selector(didTapTextButton)];
// 右端のゴミ箱ボタン
UIBarButtonItem *deleteButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemTrash
                                                                              target:self
                                                                              action:@selector(didTapDeleteButton)];
// プラスボタン、中心のテキスト、ゴミ箱ボタンの空白
UIBarButtonItem *flexibleItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
                                                                              target:nil
                                                                              action:nil];

// UIViewController#toolbarItemsに表示する順番に並べた配列を代入
self.toolbarItems = @[addButton, flexibleItem, textItem, flexibleItem, deleteButton];

Toolbarのボタンの配置はピクセル指定やAuto Layoutで行うものではありません。並べる順番に配列にして、UIViewController#toolbarItemsに代入します。

複数のボタンを並べる時に間隔を開けたい時がありますが、その時はUIBarButtonSystemItemFlexibleSpaceかUIBarButtonSystemItemFixedSpaceを使います。今回のサンプルではFlexibleSpaceを使って3つのボタンの間に空白ができるようにしています。

03-1

理解を深めるために他にも例を出してみます。

2つのボタンを両端に配置

self.toolbarItems = @[addButton, flexibleItem, deleteButton];

04-1

1つのボタンを右端に配置

self.toolbarItems = @[flexibleItem, deleteButton];

05-1

1つのボタンを左端に、テキストを中心、2つのボタンを右端に配置

self.toolbarItems = @[addButton, flexibleItem, textButton, flexibleItem, replyButton, deleteButton];

06-1

以上、NavigationBar、Toolbarへのボタン配置でした。