LoginSignup
20
23

More than 5 years have passed since last update.

Storyboardを使ってContainerView+PageViewのサンプルを作ってみた

Posted at

概要

横スクロールするメニュー+メニューに連動してメインビューが切り替わる、
SmartNews等のアプリで見られるような、簡易なサンプルを作ってみました。
ポイントはこんな感じです。
・可能な限りStoryboadを使う(+Swift)
・横スクロールするメニュー⇒ScrollView+StackView
・メインビュー⇒ContainerView+PageView

このあたりの記事を参考にさせていただきました。
http://crossbridge-lab.hatenablog.com/entry/2015/12/26/210600
http://qiita.com/nofrmm/items/5cc122876b6c3af7a21e

ソース

ざっくりとした内容しか記載していないのでソース見たい方はこちらからどうぞ
https://github.com/koji-nishida/scrollmenu-container-pageview

完成イメージ

サンプル.gif

全体図

スクリーンショット 2016-08-19 14.59.16.png

スクリーンショット 2016-08-19 15.01.04.png

メニュー部の作成

ScrollView、StackView、Buttonを配置
Constraintsは下図のような感じ(Buttonは特に制約なし)
これで端末幅に合わせて横スクロールするメニューが完成
スクリーンショット 2016-08-20 10.32.10.png

スクリーンショット 2016-08-20 10.30.10.png
ScrollViewのConstraints

スクリーンショット 2016-08-20 10.31.53.png
StackViewのConstraints

メインビュー部の作成

図のようにメニューの下にContainerViewを配置。
配置時点ではUIViewControllerがembedされているので、
UIViewControllerを消して、UIPaveViewControllerを配置しなおします。
ここでUIPaveViewControllerのCustom ClassにPageViewController.swiftを指定しておく。
スクリーンショット 2016-08-20 10.40.06.png
スクリーンショット 2016-08-20 10.39.41.png
ContainerViewのConstraints

実装部(PageViewにViewControllerをセット)

HomeViewController.swift
    var pageViewController: PageViewController!
    var menuViewControllers: Array<UIViewController> = []
    var selected: Int!

    override func viewDidLoad() {
        super.viewDidLoad()

        // PageViewControllerを取得する
        for vc in childViewControllers {
            if vc is PageViewController {
                pageViewController = vc as! PageViewController
            }

        }

        // PageViewにセットするViewControllerを生成して配列に入れる
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let firstViewController = storyboard.instantiateViewControllerWithIdentifier("FirstViewController") as! FirstViewController
        let secondViewController = storyboard.instantiateViewControllerWithIdentifier("SecondViewController") as! SecondViewController
        let thirdViewController = storyboard.instantiateViewControllerWithIdentifier("ThirdViewController") as! ThirdViewController
        let fourthViewController = storyboard.instantiateViewControllerWithIdentifier("FourthViewController") as! FourthViewController
        menuViewControllers.append(firstViewController)
        menuViewControllers.append(secondViewController)
        menuViewControllers.append(thirdViewController)
        menuViewControllers.append(fourthViewController)

        // 初期表示をメニュー2(SecondViewController)にする
        pageViewController.setViewControllers([menuViewControllers[1]], direction: .Forward, animated: false, completion: nil)
        selected = 1
    }


puts 'The best way to log and share programmers knowledge.'

ポイント
・childViewControllersからPageViewControllerを探す
 もっといい方法があれば誰か教えて下さい
・各ViewControllerをStoryboardから生成して配列で保持しておく
・初期表示するViewControllerをセット

実装部(メニュー切り替え部)

HomeViewController.swift
@IBAction func actionMenu1(sender: AnyObject) {
        self.btnMenu1.enabled = false
        self.btnMenu2.enabled = true
        self.btnMenu3.enabled = true
        self.btnMenu4.enabled = true

        // 一番左までスクロール
        scrollViewMenu.setContentOffset(CGPointMake(0, 0), animated: true);

        // 表示切り替え
        pageViewController!.setViewControllers([menuViewControllers[0]], direction: .Reverse, animated: true, completion: nil)

        selected = 0

    }

    @IBAction func actionMenu2(sender: AnyObject) {
        self.btnMenu1.enabled = true
        self.btnMenu2.enabled = false
        self.btnMenu3.enabled = true
        self.btnMenu4.enabled = true

        // 一番左までスクロール
        scrollViewMenu.setContentOffset(CGPointMake(0, 0), animated: true);

        // 表示切り替え(前回選択していたメニューの位置に応じてアニメーションの向きを設定)
        if (selected < 1) {
            pageViewController!.setViewControllers([menuViewControllers[1]], direction: .Forward, animated: true, completion: nil)
        } else {
            pageViewController!.setViewControllers([menuViewControllers[1]], direction: .Reverse, animated: true, completion: nil)
        }

        selected = 1

    }

    @IBAction func actionMenu3(sender: AnyObject) {
        self.btnMenu1.enabled = true
        self.btnMenu2.enabled = true
        self.btnMenu3.enabled = false
        self.btnMenu4.enabled = true

        // 一番右までスクロール
        let scrollWidth = scrollViewMenu.contentSize.width - scrollViewMenu.frame.size.width
        scrollViewMenu.setContentOffset(CGPointMake(scrollWidth, 0), animated: true);

        // 表示切り替え(前回選択していたメニューの位置に応じてアニメーションの向きを設定)
        if (selected < 2) {
            pageViewController!.setViewControllers([menuViewControllers[2]], direction: .Forward, animated: true, completion: nil)
        } else {
            pageViewController!.setViewControllers([menuViewControllers[2]], direction: .Reverse, animated: true, completion: nil)
        }

        selected = 2

    }

    @IBAction func actionMenu4(sender: AnyObject) {
        self.btnMenu1.enabled = true
        self.btnMenu2.enabled = true
        self.btnMenu3.enabled = true
        self.btnMenu4.enabled = false

        // 一番右までスクロール
        let scrollWidth = scrollViewMenu.contentSize.width - scrollViewMenu.frame.size.width
        scrollViewMenu.setContentOffset(CGPointMake(scrollWidth, 0), animated: true);

        // 表示切り替え
        pageViewController!.setViewControllers([menuViewControllers[3]], direction: .Forward, animated: true, completion: nil)

        selected = 3

    }

ポイント
・特になし笑

最後に

Storyboardもずいぶん便利になったなーというのが一番の感想ですかね。
一昔前ではコードをがりがり書かないとできなかったようなことが、
Storyboardでこんなに簡単に作れるようになったなーという印象です。

今回は、メニューボタンのアクションによる画面切り替えしか対応していないので、
メインビュー部分をスクロールさせることでも画面がスライドするようにしないとですね。
ContainerViewのジェスチャーをとって、画面を切り替えるという感じでしょうか。

以上

20
23
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
20
23