4
0

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.

tvOSAdvent Calendar 2017

Day 15

[tvOS] タブバーとSplitViewのメニュー開け閉め with RxTV

Last updated at Posted at 2017-12-14

tvOS Advent Calendar 2017 13日目の記事です。

今回はRxSwiftを使ってUITabBarControllerUISplitViewControllerのメニューの開け閉めを実装してみます。

2つともInterface Builder上で簡単に作成できる標準のUIコンポーネントで、これらはiOSと同じくコンテナビューコントローラの仕組みをベースに作られています。
tabbar-split.png

まずはUITabBarControllerUISplitViewControllerの開け閉めをプログラムでやるにはどういう処理を書いたらいいのか確認します。どちらも素直なAPIはないのでちょっとしたハックが必要でした。

タブバーの開け閉め

タブバーについてはStackOverflowに断片的に載っていますがそのままでは動かず、結果こういう形に落ち着きました。

extension UITabBarController {

   func showTabBar() {

        self.tabBar.alpha = 1
        self.tabBar.isHidden = false

        UIView.animate(
            withDuration: 0.5,
            delay: 0,
            usingSpringWithDamping: 1,
            initialSpringVelocity: 1,
            options: UIViewAnimationOptions.curveEaseOut,
            animations:
        {
            self.base.tabBar.frame.origin.y = 0

        }, completion: { _ in

            self.setNeedsFocusUpdate()
            self.updateFocusIfNeeded()

        })
    }

    func hideTabBar() {

        UIView.animate(
            withDuration: 0.5,
            delay: 0,
            usingSpringWithDamping: 1,
            initialSpringVelocity: 1,
            options: UIViewAnimationOptions.curveEaseOut,
            animations:
        {
            self.base.tabBar.frame.origin.y = -self.base.tabBar.bounds.height

        }, completion: { _ in

            self.tabBar.isHidden = true
            self.tabBar.alpha = 0

            if let focused = UIScreen.main.focusedView,
                focused.isDescendant(of: self.base.tabBar) {

                self.setNeedsFocusUpdate()
                self.updateFocusIfNeeded()
            }
        })
    }
}

SplitViewの開け閉め

こちらはiOSでも似たような感じになるようですね。

extension UISplitViewController {

    func hideMasterViewIfNeeded() {
        if !_isMasterViewHidden { toggleMasterView() }
    }

    func showMasterViewIfNeeded() {
        if _isMasterViewHidden { toggleMasterView() }
    }

    private func toggleMasterView() {
        let barButtonItem = displayModeButtonItem
        UIApplication.shared.sendAction(barButtonItem.action!,
        								to: barButtonItem.target,
        								from: nil,
        								for: nil)
    }

    private var _isMasterViewHidden: Bool {
        return view.subviews.contains { $0.frame.origin.x < 0 }
    }

}

開け閉めする

あとは開け閉めしたいときに上の実装を呼んであげればいいです。

    isTabBarHidden
    	.throttle(latest: true, scheduler: MainScheduler.instance)
    	.observeOn(MainScheduler.instance)
    	.subscribe(onNext: { [weak self] isHidden in
    	    if isHidden {
	    		self?.tabBarController?.hideTabBar()
	    	} else {
	    		self?.tabBarController?.showTabBar()
	    	}
    	})
    	.disposed(by: rx.disposeBag)

RxTV

上のコードのままでもいいですが、RxSwiftの世界では基本的にはbindだけで済ませられるとコードがスッキリするので、まとめましょう。
RxTVを使うと、上のようなコードは一切書かずにBinderとして実装してあるrx.isMasterViewHiddenrx.isTabBarHiddenのプロパティにそれぞれbindするだけで済みます。
https://github.com/toshi0383/RxTV

タイマーで自動ドアみたいにしてみました。

import RxSwift
import RxTV
import UIKit

class SplitViewController: UISplitViewController {

    private var disposeBag = DisposeBag()

    override func viewDidLoad() {

        super.viewDidLoad()
        
        let main = MainScheduler.instance

        Observable<Int>.timer(1.0, period: 1.0, scheduler: main)
            .map { $0 % 2 == 0 }
            .bind(to: rx.isMasterViewHidden)
            .disposed(by: disposeBag)

        Observable<Int>.timer(1.2, period: 1.2, scheduler: main)
            .map { $0 % 2 == 0 }
            .bind(to: tabBarController!.rx.isTabBarHidden)
            .disposed(by: disposeBag)

    }

}

Nov-26-2017 22-15-06.gif

やってることに比べると、だいぶコードがスッキリしてると思います。

まとめ

タブバーとSplitViewのメニュー自動開け閉めをRxSwiftとRxTVで実装してみました。RxTVは他にもrx.didUpdateFocusrx.didUpdateFocus(match:)といった便利APIを提供しているのでよかったら使ってみてください。

tvOS Advent Calendar 2017 明日は @m_yukio による「tvOS再入門」です!

4
0
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
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?