Barra de navegação e animação de transição

O comportamento de um UINavigationBar ao navegar na pilha pode parecer imprevisível e muitas vezes com erros. Mas, na verdade, é! Este artigo tem como objetivo atualizar seus conhecimentos sobre os princípios de trabalho e mostrar as possibilidades de personalização de comportamentos.

Alguma teoria geral

Se você tiver conhecimento, sinta-se à vontade para rolar diretamente para a animação.

  1. UINavigationBar é uma visualização. Normalmente, sua posição é controlada pelo UINavigationController, mas, como outras visualizações, você mesmo pode usá-lo.

  2. UINavigationItem é uma classe que descreve o estado (semelhante ao viewModel) para a configuração UINavigationBar. Apenas uma classe com propriedades que serão passadas para o UINavigationBar.

  3. O UINavigationBar contém uma matriz [UINavigationItem]. Usando os métodos pushItem, popItem e setItems, você pode animar a transição de um estado UINavigationBar para outro.

  4. Cada UIViewController contém um UINavigationItem. O próprio UINavigationController gerencia a adição dessa propriedade à pilha de itens UINavigationBar.

Mais detalhes podem ser encontrados aqui:

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