iOS のニュース系アプリ
日常的に iPhone で利用しているニュース系アプリの多くが類似したユーザインタフェースを採用しているのを見て、
汎用的なユーザインタフェースのクラスを作ってみたくなった。
以下、「ニュースパス」「グノシー」「スマートニュース」「ハッカドール」アプリのスクリーンショットを例示する。
ニュースパス (App Store)
グノシー (App Store)
スマートニュース (App Store)
ハッカドール (App Store)
今回は、同じような感じのユーザインタフェースを一つのクラスで切り替えられる仕組みを考えてみた。
PageMenuController クラスの設計と実装
完成版は github に PageMenuController として公開中。
すぐに動かしてみたい人は、上記 URL をクリックしてダウンロードするなり、clone するなりして、Xcode でビルドして、iOS Simulator で実行してね。
メニュー画面の設計
いずれのニュース系アプリに共通するのが、画面上部の横スクロールするタブ形式のメニュー画面である。
今回は、スタイル指定でこのメニュー部分を切り替え可能な仕組みを設計する。
とりあえず、先に紹介したニュース系アプリと同じ見た目にするスタイルを決める(以下参照)。
typedef NS_ENUM(NSInteger, PMKPageMenuControllerStyle) {
PMKPageMenuControllerStylePlain, // like NewsPass
PMKPageMenuControllerStyleTab, // like Gunosy
PMKPageMenuControllerStyleSmartTab, // like SmartNews
PMKPageMenuControllerStyleHackaTab // like Hackadoll
};
- メニュー画面は、一番簡単な UIScrollView に UILabel を追加する方法で実装する。
- メニューのタイトルや背景色は、UILabel への設定で実現する。
- メニューのタップによるコンテンツ切り替えは、UILabel 上での UITapGestureRecognizer を処理する。
- メニュー毎に切り替わるコンテンツ部分は、UIPageViewController を利用する。
- コンテンツ画面上での左右へのスワイプ操作での画面切り替えは、UIPageViewController の機能をそのまま利用する。
Initializer は以下の仕様にする。
-(instancetype)initWithControllers:(NSArray<UIViewController *> *)controllers
menuStyle:(PMKPageMenuControllerStyle)menuStyle
topBarHeight:(CGFloat)topBarHeight;
- controllers 配列は、コンテンツ部分の UIViewController サブクラスである。
- menuStyle は、上述したメニュースタイルのいずれかを指定する。
- topBarHeight は、statusBar や navigationBar の高さを指定する。
詳細な実装に関しては、PageMenuController の PMKPageMenuController.m ファイルを参照して欲しい。
各メニュー画面のスクリーンショットとスタイルの指定方法
PageMenuController クラスを利用したい UIViewController サブクラスで、次のコードを記述する。
@property (nonatomic,strong) PMKPageMenuController * pageMenuController;
コンテンツ管理用の配列なども準備しておく。以下のようなコードを loadView に記述する。
より具体的な記述例は、PageMenuController 内の RootViewController.m ファイルを参照してね。
// UIViewController のサブクラスを管理する配列
NSMutableArray * controllers = [NSMutableArray new];
// 以下のような感じで必要な UIViewController を追加する
UIViewController * vc = [UIViewController new];
vc.title = @"Page Title"; // このタイトルがメニューに表示されるよ
[controllers addObject:vc];
// ステータスバーの高さを求める
CGFloat statusBarHeight = [UIApplication sharedApplication].statusBarFrame.size.height;
以下、メニュー画面のスクリーンショットと指定したスタイル名を列挙する。
「ニュースパス」っぽいメニュー画面(PMKPageMenuControllerStylePlain を指定)
self.pageMenuController = [[PMKPageMenuController alloc]
initWithControllers:controllers
menuStyle:PMKPageMenuControllerStylePlain
topBarHeight:statusBarHeight];
「グノシー」っぽいメニュー画面(PMKPageMenuControllerStyleTab を指定)
self.pageMenuController = [[PMKPageMenuController alloc]
initWithControllers:controllers
menuStyle:PMKPageMenuControllerStyleTab
topBarHeight:statusBarHeight];
「スマートニュース」っぽいメニュー画面(PMKPageMenuControllerStyleSmartTab を指定)
self.pageMenuController = [[PMKPageMenuController alloc]
initWithControllers:controllers
menuStyle:PMKPageMenuControllerStyleSmartTab
topBarHeight:statusBarHeight];
「ハッカドール」っぽいメニュー画面(PMKPageMenuControllerStyleHackaTab を指定)
self.pageMenuController = [[PMKPageMenuController alloc]
initWithControllers:controllers
menuStyle:PMKPageMenuControllerStyleHackaTab
topBarHeight:statusBarHeight];
メニュー画面のカスタマイズ
PMKPageMenuControllerStyleTab と PMKPageMenuControllerStyleSmartTab スタイルの背景色を変更する場合は、UIColor オブジェクトを格納した NSArray を Initializer に引数として渡すことで実現できる。
-(instancetype)initWithControllers:(NSArray<UIViewController *> *)controllers
menuStyle:(PMKPageMenuControllerStyle)menuStyle
menuColors:(NSArray<UIColor *> *)menuColors
topBarHeight:(CGFloat)topBarHeight;
また、各メニュー項目をカスタマイズしたい場合は、以下の Delegate が利用可能である。
// メニューの準備が完了した後に一度だけ呼び出される
-(void)pageMenuController:(PMKPageMenuController *)pageMenuController
didPrepareMenuItems:(NSArray<PMKMenuItem *> *)menuItems;
// メニュー項目がタップされた際に呼び出される
-(void)pageMenuController:(PMKPageMenuController *)pageMenuController
didSelectMenuItem:(PMKMenuItem *)menuItem
atMenuIndex:(NSUInteger)index;
Delegate で引き渡される PMKMenuItem は、次のように定義してある。
ただし、badgeValue と borderColor は、PMKPageControllerStyleHackaTab の時だけ有効である。
@interface PMKMenuItem : NSObject
@property (nonatomic,copy) NSString * title; // set automatically
@property (nonatomic,assign) NSInteger tag; // default: 0
@property (nonatomic,copy) NSString * badgeValue; // default: nil
@property (nonatomic,strong) UIColor * titleColor; // set automatically
@property (nonatomic,strong) UIColor * backgroundColor; // set automatically
@property (nonatomic,strong) UIColor * borderColor; // set automatically
@property (nonatomic,getter=isEnabled) BOOL enabled; // default: YES
@property (nonatomic,readonly,getter=isSelected) BOOL selected; // default: NO
@property (nonatomic,readonly) PMKPageMenuControllerStyle menuStyle;
@end
ダウンロード
Xcode Project 一式 は、github から入手できます。