その後のその後

iOSエンジニア 堤 修一のブログ github.com/shu223

スクロール付きタブバー "InfiniTabBar"

先日の OGActionChooser に引き続き、オープンソースのUIコンポーネントの紹介です。


ソーシャルゲーム系のアプリでちょくちょく見かけるのが、スクロールするタブバー。



あまりわかりやすいUIとはいえないので、ネイティブ実装する場合にこのUIを採用するケースはあまりないのですが、メニューの多いアプリのUIの検討の場にはちょくちょく出てきます。


そういう場合に InfiniTabBar を使えば、サクッとスクロール付きタブバーをつくって試すことができます。


基本的な使い方

InfiniTabBar のAPIは、UITabBarとほぼ同様の API となっているため、使い方が非常に簡単です。以下が基本的な実装手順です。


1. ソースコードをダウンロード
https://github.com/iosdeveloper/InfiniTabBar


2. ヘッダインポート
#import "InfiniTabBar.h"


3. プロトコルへの準拠を宣言


4. オブジェクト生成、表示
UITabBarと同様、UITabBarItem を必要な数だけ生成して、NSArrayオブジェクトに入れて initWithItems メソッドに渡します。

UITabBarItem *favorites = [[UITabBarItem alloc] initWithTabBarSystemItem:UITabBarSystemItemFavorites tag:0];
UITabBarItem *topRated = [[UITabBarItem alloc] initWithTabBarSystemItem:UITabBarSystemItemTopRated tag:1];
UITabBarItem *featured = [[UITabBarItem alloc] initWithTabBarSystemItem:UITabBarSystemItemFeatured tag:2];
UITabBarItem *recents = [[UITabBarItem alloc] initWithTabBarSystemItem:UITabBarSystemItemRecents tag:3];
UITabBarItem *contacts = [[UITabBarItem alloc] initWithTabBarSystemItem:UITabBarSystemItemContacts tag:4];
UITabBarItem *history = [[UITabBarItem alloc] initWithTabBarSystemItem:UITabBarSystemItemHistory tag:5];
UITabBarItem *bookmarks = [[UITabBarItem alloc] initWithTabBarSystemItem:UITabBarSystemItemBookmarks tag:6];
UITabBarItem *search = [[UITabBarItem alloc] initWithTabBarSystemItem:UITabBarSystemItemSearch tag:7];
UITabBarItem *downloads = [[UITabBarItem alloc] initWithTabBarSystemItem:UITabBarSystemItemDownloads tag:8]; downloads.badgeValue = @"2";
UITabBarItem *mostRecent = [[UITabBarItem alloc] initWithTabBarSystemItem:UITabBarSystemItemMostRecent tag:9];
UITabBarItem *mostViewed = [[UITabBarItem alloc] initWithTabBarSystemItem:UITabBarSystemItemMostViewed tag:10];

// Tab bar
InfiniTabBar *tabBar = [[InfiniTabBar alloc] initWithItems:[NSArray arrayWithObjects:favorites,
												   topRated,
												   featured,
												   recents,
												   contacts,
												   history,
												   bookmarks,
												   search,
												   downloads,
												   mostRecent,
												   mostViewed, nil]];

tabBar.infiniTabBarDelegate = self;
   
[self.view addSubview:tabBar];

上記サンプルコードではUITabBarItem の生成に initWithTabBarSystemItem:tag: メソッドを使用していますが、任意の画像、タイトルを指定する場合は initWithTitle:image:tag: を使用します。


5. デリゲートメソッドを実装する
InfiniTabBarDelegate の infiniTabBar:didScrollToTabBarWithTag: と、infiniTabBar:didSelectItemWithTag: を実装します。

- (void)infiniTabBar:(InfiniTabBar *)tabBar didScrollToTabBarWithTag:(int)tag {
	self.dLabel.text = [NSString stringWithFormat:@"%d", tag + 1];
}

- (void)infiniTabBar:(InfiniTabBar *)tabBar didSelectItemWithTag:(int)tag {
	self.fLabel.text = [NSString stringWithFormat:@"%d", tag + 1];
}

挙動を確認したところ、前者はスクロール完了時に表示されているページのタグが、後者はユーザーが選択したタブアイテムのタグが引数に入ってくるようです。


カスタマイズする

InfiniTabBar は UIScrollView のサブクラスなので、同様のカスタマイズが可能です。


たとえば、pagingEnabled にNOをセットすれば、ページ単位のスクロールをオフにできます。

tabBar.pagingEnabled = NO;

デフォルトではオンなのですが、メニューに続きがある


他に、スクロールインジケータをオフにしたり、バウンスしないようにしたりと、UIScrollView でおなじみの設定が行えます。

tabBar.showsHorizontalScrollIndicator = NO;
tabBar.bounces = NO;


ちなみに、タブのボタンのレイアウトは、InfiniTabBar.m の initWithItems: メソッド内で以下のようにハードコーディングされています。

float x = 0.0;

for (double d = 0; d < ceil(items.count / 5.0); d ++) {
	UITabBar *tabBar = [[UITabBar alloc] initWithFrame:CGRectMake(x, 0.0, 320.0, 49.0)];
	tabBar.delegate = self;
	
	int len = 0;
	
	for (int i = d * 5; i < d * 5 + 5; i ++)
		if (i < items.count)
			len ++;
	
	tabBar.items = [items objectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(d * 5, len)]];
	
	[self addSubview:tabBar];
	
	[self.tabBars addObject:tabBar];
	
	[tabBar release];
	
	x += 320.0;
}

self.contentSize = CGSizeMake(x, 49.0);

なので、たとえばボタンを4つずつにしたい等、UITabItemの並びをカスタマイズしたい場合は、InfiniTabBar 自体のソースに手を入れる必要がありそうです。