ナビゲーションバーとトランジションアニメーション

スタックをナビゲートするときのUINavigationBarの動作は、予測できないように見え、多くの場合バグがあります。しかし、実際にはそうです!この記事は、作業の原則に関する知識を更新し、動作をカスタマイズする可能性を示すことを目的としています。

いくつかの一般的な理論

知識がある場合は、アニメーションに直接スクロールしてください。

  1. UINavigationBarはビューです。通常、その位置はUINavigationControllerによって制御されますが、他のビューと同様に、自分で使用できます。

  2. UINavigationItemは、UINavigationBar構成の状態(viewModelと同様)を記述するクラスです。UINavigationBarに渡されるプロパティを持つクラスのみ。

  3. UINavigationBarには、配列[UINavigationItem]が含まれています。pushItem、popItem、およびsetItemsメソッドを使用して、あるUINavigationBar状態から別の状態への遷移をアニメーション化できます。

  4. 各UIViewControllerにはUINavigationItemが含まれています。UINavigationController自体が、UINavigationBarアイテムのスタックへのこのプロパティの追加を管理します。

詳細については、こちらをご覧ください。

UINavigationBar-. :

UINavigationBar . :

  • prompt ( )

  • largeTitleDisplayMode

UINavigationBar – view, – , , .

: – navigationBar.backgroundColor, – navigationBar.barTintColor.

– backgroundColor. , backgroundColor – view -. 

prompt- .

, transition UINavigationBar . UIViewControllerAnimatedTransitioning UINavigationBar. 

: ,

safeArea . additionalSafeAreaInsets UIViewController- :

contentView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true

UINavigationController UINavigationControllerDelegate. , .

class NavigationController: UINavigationController, UINavigationControllerDelegate { }

UINavigationController-.

navigationController.delegate = navigationController

. UIViewController navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) transitionCoordinator safeArea.

guard let fromViewController = viewController.transitionCoordinator?.viewController(forKey: .from) 

else { return }

//   .     , ,  pop

let isPopped = !navigationController.viewControllers.contains(fromViewController)

 

//  ,      

viewController.transitionCoordinator?.animate { context in

    guard let from = context.viewController(forKey: .from),

          let to = context.viewController(forKey: .to)

    else { return }

    

    //   

    //      ,   safeArea 

    //     

    UIView.setAnimationsEnabled(false)

    let diff = to.view.safeAreaInsets.top - from.view.safeAreaInsets.top

    //      

    to.additionalSafeAreaInsets.top = -diff

    to.view.layoutIfNeeded()

    UIView.setAnimationsEnabled(true)

    

    //  safeArea

    to.additionalSafeAreaInsets.top = 0

    to.view.layoutIfNeeded()

    

    guard isPopped else { return }

 

    //     pop-

    //      additionalSafeAreaInsets  

    from.view.frame.origin.y = diff

    from.view.frame.size.height += max(0, -diff)

    

} completion: { context in

    guard let from = context.viewController(forKey: .from),

          let to = context.viewController(forKey: .to)

    else { return }

    

    from.additionalSafeAreaInsets.top = 0

    to.additionalSafeAreaInsets.top = 0

}

, :

– . , UINavigationBar. , , . 

, :)

: Rtishchev Evgenii https://twitter.com/katleta3000/status/1259400743771156480

https://stackoverflow.com/questions/39515313/animate-navigation-bar-bartintcolor-change-in-ios10-not-working

navigation bar: https://www.programmersought.com/article/1594185256/




All Articles