14
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[iOS] ニュース系アプリのユーザインタフェースの実装

Last updated at Posted at 2016-12-07

iOS のニュース系アプリ

日常的に iPhone で利用しているニュース系アプリの多くが類似したユーザインタフェースを採用しているのを見て、
汎用的なユーザインタフェースのクラスを作ってみたくなった。
以下、「ニュースパス」「グノシー」「スマートニュース」「ハッカドール」アプリのスクリーンショットを例示する。

ニュースパス (App Store)
ニュースパス画像

グノシー (App Store)
グノシー画像

スマートニュース (App Store)
スマートニュース画像

ハッカドール (App Store)
ハッカドール

今回は、同じような感じのユーザインタフェースを一つのクラスで切り替えられる仕組みを考えてみた。

PageMenuController クラスの設計と実装

完成版は github に PageMenuController として公開中。
すぐに動かしてみたい人は、上記 URL をクリックしてダウンロードするなり、clone するなりして、Xcode でビルドして、iOS Simulator で実行してね。

メニュー画面の設計

いずれのニュース系アプリに共通するのが、画面上部の横スクロールするタブ形式のメニュー画面である。
今回は、スタイル指定でこのメニュー部分を切り替え可能な仕組みを設計する。
とりあえず、先に紹介したニュース系アプリと同じ見た目にするスタイルを決める(以下参照)。

PageMenuController.h
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 は以下の仕様にする。

PageMenuController.h
-(instancetype)initWithControllers:(NSArray<UIViewController *> *)controllers
                         menuStyle:(PMKPageMenuControllerStyle)menuStyle
                      topBarHeight:(CGFloat)topBarHeight;
  • controllers 配列は、コンテンツ部分の UIViewController サブクラスである。
  • menuStyle は、上述したメニュースタイルのいずれかを指定する。
  • topBarHeight は、statusBar や navigationBar の高さを指定する。

詳細な実装に関しては、PageMenuControllerPMKPageMenuController.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 を指定)

PMKPageMenuControllerStylePlain

self.pageMenuController = [[PMKPageMenuController alloc]
                            initWithControllers:controllers
                            menuStyle:PMKPageMenuControllerStylePlain
                            topBarHeight:statusBarHeight];

「グノシー」っぽいメニュー画面(PMKPageMenuControllerStyleTab を指定)

PMKPageMenuControllerStyleTab

self.pageMenuController = [[PMKPageMenuController alloc]
                            initWithControllers:controllers
                            menuStyle:PMKPageMenuControllerStyleTab
                            topBarHeight:statusBarHeight];

「スマートニュース」っぽいメニュー画面(PMKPageMenuControllerStyleSmartTab を指定)

PMKPageMenuControllerStyleSmartTab

self.pageMenuController = [[PMKPageMenuController alloc]
                            initWithControllers:controllers
                            menuStyle:PMKPageMenuControllerStyleSmartTab
                            topBarHeight:statusBarHeight];

「ハッカドール」っぽいメニュー画面(PMKPageMenuControllerStyleHackaTab を指定)

PMKPageMenuControllerStyleHackaTab

self.pageMenuController = [[PMKPageMenuController alloc]
                            initWithControllers:controllers
                            menuStyle:PMKPageMenuControllerStyleHackaTab
                            topBarHeight:statusBarHeight];

メニュー画面のカスタマイズ

PMKPageMenuControllerStyleTabPMKPageMenuControllerStyleSmartTab スタイルの背景色を変更する場合は、UIColor オブジェクトを格納した NSArray を Initializer に引数として渡すことで実現できる。

PMKPageMenuController.h
-(instancetype)initWithControllers:(NSArray<UIViewController *> *)controllers
                         menuStyle:(PMKPageMenuControllerStyle)menuStyle
                        menuColors:(NSArray<UIColor *> *)menuColors
                      topBarHeight:(CGFloat)topBarHeight;

また、各メニュー項目をカスタマイズしたい場合は、以下の Delegate が利用可能である。

PMKPageMenuController.h
// メニューの準備が完了した後に一度だけ呼び出される
-(void)pageMenuController:(PMKPageMenuController *)pageMenuController
      didPrepareMenuItems:(NSArray<PMKMenuItem *> *)menuItems;
// メニュー項目がタップされた際に呼び出される
-(void)pageMenuController:(PMKPageMenuController *)pageMenuController
        didSelectMenuItem:(PMKMenuItem *)menuItem
              atMenuIndex:(NSUInteger)index;

Delegate で引き渡される PMKMenuItem は、次のように定義してある。
ただし、badgeValueborderColor は、PMKPageControllerStyleHackaTab の時だけ有効である。

PMKPageMenuController.h
@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 から入手できます。

14
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?