24/7 twenty-four seven

iOS/OS X application programing topics.

UINavigationBar に複数の UIBarButtonItem を配置するには

UINavigationBar は基本的に左右 (leftBarButtnItem, rightarButtonItem) に一つずつしかボタンを配置することができません。
しかし、ちょっと工夫をするとその制限を突破することができます。
(まあ物理的なスペースの関係でせいぜい2つか3つがやっとなのですけどね)

方法その1. UIToolbar を UIBarButtonItem として配置し、その中に UIBarButtonItem を並べる


もっとも見た目がキレイに仕上がる方法です。

UINavigationBar の leftBarButtnItem と rightarButtonItem は UIBarButtonItem のインスタンスをそれぞれ1つずつしか代入できませんが、UIToolbar を UIBarButtonItem として作成することで、その UIToolbar に複数のボタンを配置することができるようになります。

UIBarButtonItem *sendButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Send", nil) style:UIBarButtonItemStyleBordered target:self action:@selector(send:)];

UIBarButtonItem *cameraButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCamera target:self action:@selector(cancel:)];
cameraButton.style = UIBarButtonItemStyleBordered;

UIBarButtonItem *space = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];

UIToolbar *toolbar = [[MyToolbar alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 110.0f, 44.0f)];
toolbar.backgroundColor = [UIColor clearColor];
toolbar.autoresizingMask = UIViewAutoresizingFlexibleHeight;
UIBarButtonItem *toolbarBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:toolbar];
[toolbar release];

toolbar.items = [NSArray arrayWithObjects:space, cameraButton, sendButton, nil];
[space release];
[cameraButton release];
[sendButton release];

self.navigationItem.rightBarButtonItem = toolbarBarButtonItem;
[toolbarBarButtonItem release];


ただ、標準の UIToolbar の外観は UINavigationBar の外観と微妙な差異があるので、このままでは境界が目立ってしまいます。


そこで UIToolbar のサブクラスを作成し、空の drawRect: メソッドでオーバーライドし、標準の描画を無効にします。

@interface MyToolbar : UIToolbar
@end

@implementation MyToolbar

- (void)drawRect:(CGRect)rect {
    
}

@end


すると、このような状態になります。


真っ黒になってしまったので、背景色を透明に設定します。
drawRect: メソッドの処理は backgroundColor と無関係というのがミソですね。

toolbar.backgroundColor = [UIColor clearColor];


キレイになりました。


もし、横方向の画面をサポートする場合、ナビゲーションバーは横方向では 30 ピクセルの幅に変わりますので、ツールバーの autoresizingMask プロパティに UIViewAutoresizingFlexibleHeight を設定しておきましょう。

toolbar.autoresizingMask = UIViewAutoresizingFlexibleHeight;



UIViewAutoresizingFlexibleHeight を指定しない場合は下のようになります。すこしボタンの大きさがアンバランスですね。


色をつけると違いが分かりやすくなります。


tintColor を設定すれば色も変えられます。

方法その2. UISegmentedControl をボタンのように使用する

標準のメールアプリでも採用されている方法です。
メールアプリの「前へ」「次へ」のように同じような動作をするボタンを並べる場合は良い方法だと思います。


titleView プロパティに乗せると3つのボタンを並べても余裕があります。


UISegmentedControl をボタンとして使用するには、momentary プロパティを YES に、アクションは UIControlEventValueChanged を設定します。

segmentedControl = [[UISegmentedControl alloc] initWithItems:items];
segmentedControl.segmentedControlStyle = UISegmentedControlStyleBar;
segmentedControl.momentary = YES;
segmentedControl.frame = CGRectMake(segmentedControl.frame.origin.x, segmentedControl.frame.origin.y, segmentedControl.frame.size.width + 16.0f * [items count], segmentedControl.frame.size.height);
[segmentedControl addTarget:self action:@selector(segmentedControlAction:) forControlEvents:UIControlEventValueChanged];
[self.navigationItem setTitleView:segmentedControl];
[segmentedControl release];

方法その3. UIToolbar を上部のナビゲーションバーの位置に配置する

簡単ですがオススメしません。
というのも UIToolbar は画面の下部に配置するようにデザインされているため、上部に配置するとどうしても外観に違和感がでてしまうからです。
(iOS 4.x までの iPhone の場合。iPad のツールバーは上下どちらに配置してもいいようにデザインされている。)


ナビゲーションバーの位置に配置したツールバー。
ステータスバーとの境界が不自然ですね。