【iOS11】UINavigationControllerで遷移時のアニメーションがおかしくなる時の対処法【高さ変更】

どうも。Reoです。

3記事目になりました。iOS11+UINavigationControllerシリーズです。

1記事目「【Swift4】UINavigationControllerのNavigationBarをカスタマイズしてみた。【高さ変更】
2記事目「【Swift4】UINavigationControllerのToolbarをカスタマイズしてみた【高さ変更】

 

さて今回は1記事目でUINavigationController上にあるNavigationBarの高さを変更したせいで、遷移時のアニメーションがおかしくなってしまった!というお話をしていきます。

具体的には以下のgifのようになってしまいます。

左がiOS10で動かした場合、右がiOS11で動かした場合です。

なんか遷移時に上下に伸縮しているのがわかるでしょうか。

 

UINavigationBarのカスタマイズの方の記事を元にしていきますので、よろしくお願いします。

 

Push時のアニメーションを直す!

まずは、UINavigationControllerを継承したクラス内に以下のように書きます。

前回の続きの場合は、CustomNavigationController内に書いています。

    override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()
        //なんでもいいから値をいれておくとアニメーションが直る
        self.navigationBar.frame.size.height = 50
    }

これでひとまずpushは直りました。

本当に何入れても直るのが不思議なんですが、一応ちゃんと実際と同じ高さを入れておくのがいいと思います。

適当に書いたら直ったしとても冴えてる(`・ω・´+)

でもまだpop時のアニメーションがかくつきます。

 

Pop時のアニメーションを直す!

こっちは結構荒療治なんですが、デフォルトのナビゲーションアイテムを使わないと直ります。

遷移先のViewController(SecondViewControllerとしました)で、ナビゲーションアイテムを追加します。

class SecondViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        self.view.backgroundColor = UIColor.yellow
        
        let backBtn = UIBarButtonItem(title: "戻る", style: .plain, target: self, action: #selector(self.backBtnTapped))
        self.navigationItem.leftBarButtonItem = backBtn
        
    }
    
    @objc func backBtnTapped(){
        self.navigationController?.popViewController(animated: true)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
}

 

これで直りました。

 

デデーン!

以上と言いたいんですが、ナビゲーションアイテムをデフォルトから自分で設定したものに変更すると、何故かinteractivePopGestureRecognizerが効かなくなるんですよね。スワイプで戻れるやつです。

//なぜかきかなくなる
self.interactivePopGestureRecognizer?.isEnabled = true

何故なんだ・・・。

自分のアプリでは使わないんですが、気になったので直してみました。

 

interactivePopGestureRecognizerを効くようにする!

CustomNavigationController内でデリゲートの設定をします。

    override func viewDidLoad() {
        super.viewDidLoad()
        //なぜかきかなくなる・・・
        self.interactivePopGestureRecognizer?.isEnabled = true
        
        //上記対処をdelegateでする
        self.interactivePopGestureRecognizer?.delegate = self
    }

あとはextensionで追加

extension CustomNavigationController:UIGestureRecognizerDelegate {
    func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        guard gestureRecognizer is UIScreenEdgePanGestureRecognizer else { return true }
        return viewControllers.count > 1
    }
}

これでスワイプでpopできるようになりました。

 

 

うひょー

 
今回のもgithubにあげたコードに追加しときました。
uruly/CustomNavigationController-CustomNavigationBar

 

ハマるかなと思ったけど勘が冴えているというか、案外あっさり解決しました。

おかげさまで、RobinのiPhoneX対応が終わりました。∩(〃・ω・〃)∩ ばんざーい
もう少しデバッグして明日中には審査に出します〜。

ではでは。

 

コメントは認証制です。詳しくは下記の注意をお読みください。お気軽にコメントお願いします!

Write a Comment

コメント時の注意

「Twitter」「Facebook」「Google+」「WordPress」のいずれかのアカウントをお持ちの方は各アカウントと連携することでコメントできます。 コメントしたことはSNSに流れませんので、アカウントをお持ちの方はこちらの方法でコメントを投稿して下さると嬉しいです。 アカウントをお持ちでない方はメールアドレスで投稿することができます。 初回コメント時は承認後に表示されます。

Related Memo...

記事を書くほどでもないけれどメモっておきたいこと

テスト投稿。

例えばiphone7 の画面サイズ

750 × 1334
半分375 × 667

iOS

UINavigationController + UIScrollView の組み合わせで使っている時に謎の余白ができる時

UINavigationController + UIScrollView の組み合わせで使っていて、UIScrollView 上に AutoLayout で上下左右0で View を設置しているのに、30px程度上にずれてしまうとき。

`navigationController.navigationBar.isTranslucent = false` にすると直るかもしれない。

ScrollView上のコンテンツとNavigationBarの重なっているところが透過していたら多分これで直せるはず。

通常のターゲットではちゃんと動いているのに、iOSSnapshotTestCase を用いたテストでだけこの対応が必要なのよくわからないけれど。。。

iOS

UITableView.RowAnimation の .none はアニメーションするよ

UITableView.RowAnimation の .none はアニメーションがnoneなわけじゃなく、デフォルトの設定を使うよという意味らしい。

The inserted or deleted rows use the default animations.

なのでアニメーションしちゃう。今更の気づき。

 

iOS
more