トレンドトピックというGoogleトレンドとTwitterトレンドのリスト、そこからニュース, ブログ, ツイートの検索結果を表示するアプリをリリースしてます。
f:id:tilfin:20110707160041p:image
バージョン 1.8からTwitterトレンドを追加するにあたり、既存のGoogleトレンドのリストとどう切り替えUIを用意するか考えて、Tab Bar を使うことにしました。
ただ、通常の Tab Bar はテキストがアイコンの下にくるため、49ピクセル使ってしまいます。今回の切り替えでは2項目しかないため、左にアイコンを右にテキストを置くようにしたいと単純に考えました(iPad版では画面に余裕があるため普通に使っています)。

結果から言うと UITabBar を継承してどうにかするのは非常に難しいことがわかりました。layoutSubviewsメソッドでアイコンの位置を変えても、項目がタップされる度に元に戻ってしまいます。
そこでもうUIButtonを2つ並べてイメージをセットして Tab Bar を実現することに。

イメージの作成

Tab Barのアイコンに対してエフェクトをどうかけるのか調べるのは大変なので、そういう状態の静止画を撮れるサンプリングプロジェクトを作りました。

CustomTabBar.h
1
2
3
4
5
#import <Foundation/Foundation.h>
@interface CustomTabBar : UITabBar {
}
- (void)shiftPosition;
@end
CustomTabBar.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#import "CustomTabBar.h"
@implementation CustomTabBar
- (void)shiftPosition {
for (UIView *item inself.subviews) {
for (UIView *view_ in item.subviews) {
NSString *className = NSStringFromClass(\[view_ class\]);
if (\[className isEqualToString:@"UITabBarSwappableImageView"\]) {
CGRect frame_ = view_.frame;
frame_.origin.x = 0;
frame_.origin.y += 5;
view_.frame = frame_;
}
}
}
}
@end

上記の CustomTabBar を使った UITabBar に項目をセットした状態にします。
f:id:tilfin:20110707160042p:image
実行時にボタンを押すと shiftPosition メソッドが呼ばれるようにしておき、その都度でスクリーンショットをとります。UITabBarSwappableImageView というドキュメント非公開のクラスがアイコンの ImageView クラスになります。
f:id:tilfin:20110707160043p:image
あとはスクリーンショットから画像を切り出して、通常時と選択時のpngファイルを作ります。これをノーマルとRetina向けにそれぞれ行います。

Interface Builder

実際のアプリにおいて、IBで適用します。Round Rect Buttonを二個配置して、TypeをCustomにします。
f:id:tilfin:20110707160040p:image
各ボタンにState ConfigがDefaultとSelectedのときにBackgroundをセットします。InsetのLeftを36にしてアイコンのスペースをとってテキストが始まるようにします。

あとがき

詳しくは書けませんが iOS 5 SDK Beta 2 のリリースノートをみると、これが正攻法のように思えてきました。