異なるビューのUINavigationBar
で2つの異なるバーティントカラーを使用しています。私は両方のビューでその方法で色を変更していません:
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.navigationBar.barTintColor = COLOR
}
戻るボタンをタップすると、色がスムーズに変更されません(最後の1秒間に点滅が表示されます)。
ただし、[戻る]ボタンをタップする代わりにビューをスワイプするだけで問題ありません。
両方の状況でスムーズに移行するにはどうすればよいですか?
私は最も使いやすい最終的なソリューションをコーディングしました(独自のビューコントローラーで多くのオーバーライドを使用する必要はありません)。 iOS 10で完全に動作し、独自の目的で簡単に採用できます。
あなたは GitHub Gist でクラスの完全なコードと詳細なガイドを確認できます。Stackoverflowは大量のコードを格納するためのものではありません。
ダウンロードSwiftファイル。動作させるには、ColorableNavigationController
の代わりにUINavigationController
を使用し、必要な子ビューコントローラをNavigationBarColorable
プロトコルに採用してください。
例:
class ViewControllerA: UIViewController, NavigationBarColorable {
public var navigationBarTintColor: UIColor? { return UIColor.blue }
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Push", style: .plain, target: self, action: #selector(self.showController))
}
func showController() {
navigationController?.pushViewController(ViewControllerB(), animated: true)
}
}
class ViewControllerB: UIViewController, NavigationBarColorable {
public var navigationBarTintColor: UIColor? { return UIColor.red }
}
let navigationController = ColorableNavigationController(rootViewController: ViewControllerA())
この種類のアニメーションを実現するには、UIViewControllerTransitionCoordinator
を Appleドキュメント として使用する必要があります。
UIViewControllerTransitionCoordinatorプロトコルを採用するオブジェクトは、ビューコントローラーの遷移に関連付けられたアニメーションをサポートします。(...)
したがって、すべてのUIViewController
は独自のtransitionController
を持っています。これを取得するには、UIViewControllerClass
を呼び出す必要があります。
self.transitionCoordinator()
ドキュメント から:
アクティブな遷移コーディネーターオブジェクトを返します。
したがって、必要な結果を得るには、viewController transitionCoordinatiorにanimateAlongsideTransition
メソッドを実装する必要があります。 backButton
をクリックしてスワイプして戻ると、アニメーションが機能します。
例:
最初のコントローラー:
_class ViewControllerA: UIViewController {
override func loadView() {
super.loadView()
title = "A"
view.backgroundColor = .white
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "NEXT", style: .plain, target: self, action: #selector(self.showController))
setColors()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
animate()
}
func showController() {
navigationController?.pushViewController(ViewControllerB(), animated: true)
}
private func animate() {
guard let coordinator = self.transitionCoordinator else {
return
}
coordinator.animate(alongsideTransition: {
[weak self] context in
self?.setColors()
}, completion: nil)
}
private func setColors() {
navigationController?.navigationBar.tintColor = .black
navigationController?.navigationBar.barTintColor = .red
}
}
_
2番目のコントローラー:
_class ViewControllerB : UIViewController {
override func loadView() {
super.loadView()
title = "B"
view.backgroundColor = .white
setColors()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
animate()
}
override func willMove(toParentViewController parent: UIViewController?) { // tricky part in iOS 10
navigationController?.navigationBar.barTintColor = .red //previous color
super.willMove(toParentViewController: parent)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
navigationController?.navigationBar.barTintColor = .blue
}
private func animate() {
guard let coordinator = self.transitionCoordinator else {
return
}
coordinator.animate(alongsideTransition: {
[weak self] context in
self?.setColors()
}, completion: nil)
}
private func setColors(){
navigationController?.navigationBar.tintColor = .black
navigationController?.navigationBar.barTintColor = .blue
}
}
_
UPDATE iOS 10
IOS 10では、トリッキーな部分はsecond ViewControllerにwillMoveTo(parentViewController parent: UIViewController?)
を追加することです。そして、navigationBar tintColor
をpreviousコントローラのカラー値に設定します。また、viewDidAppear
メソッドのsecond ViewControlerは、_navigationBar.tintColor
_をsecond viewController。
私の例をチェックしてください githubのプロジェクト
これは私のために働きました:
override func willMove(toParent parent: UIViewController?) {
super.willMove(toParent: parent)
navigationController?.navigationBar.barTintColor = previous view controller's navigation bar color
}
私はちょうど不思議です。同じ目的でUINavigationControllerDelegate
を使用します。 navigationController(_:willShow:)
では、transitionCoordinator?.animate(alongsideTransition:completion:)
を使用してアニメーションを開始します。新しいコントローラーをプッシュするときはうまくいきますが、popはそうではありません。
func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
let dst = viewController as! ViewController
guard animated else {
navigationController.navigationBar.barTintColor = dst.navigationBarColor
navigationController.navigationBar.tintColor = dst.tintColor
navigationController.navigationBar.barStyle = dst.barStyle
return
}
navigationController.transitionCoordinator?.animate(alongsideTransition: { context in
navigationController.navigationBar.barTintColor = dst.navigationBarColor
navigationController.navigationBar.tintColor = dst.tintColor
navigationController.navigationBar.barStyle = dst.barStyle
}, completion: { context in
if context.isCancelled {
let source = context.viewController(forKey: UITransitionContextViewControllerKey.from) as! ViewController
navigationController.navigationBar.barTintColor = source.navigationBarColor
navigationController.navigationBar.tintColor = source.tintColor
navigationController.navigationBar.barStyle = source.barStyle
}
})
それがプッシュでは機能するがポップでは機能しない理由はありますか?