рдкреЙрдк рдЕрдк! IOS рдкрд░ рдкреНрд░рд╕рд╛рд░рд┐рдд

рдирдорд╕реНрдХрд╛рд░, рд╣реЗрдмреНрд░! рд╣рд░ рдХреЛрдИ рдЙрддреНрддрд░рджрд╛рдпреА рдХреНрд╖реБрдзрд╛ рдкрд╕рдВрдж рдХрд░рддрд╛ рд╣реИред рдФрд░ рднреА рдмреЗрд╣рддрд░ рдЬрдм рдЙрдирдХреЗ рдкрд╛рд╕ рдкреНрд░рд╛рд╕рдВрдЧрд┐рдХ рдПрдирд┐рдореЗрд╢рди рд╣реЛрдВред рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рдореИрдВ рд╕рднреА "рдорд╛рдВрд╕" рдХреЗ рд╕рд╛рде рдмрддрд╛рдКрдВрдЧрд╛ рдФрд░ рджрд┐рдЦрд╛рдКрдВрдЧрд╛ рдХрд┐ рдХреИрд╕реЗ рдкреЙрдк-рдЕрдк рд╕реНрдХреНрд░реАрди рдХреЗ рд╕рд╛рде рд╕рдм рдХреБрдЫ рдареАрдХ рд╕реЗ рджрд┐рдЦрд╛рдирд╛, рдЫрд┐рдкрд╛рдирд╛, рдореЛрдбрд╝рдирд╛, рдШреВрдордирд╛ рдФрд░ рдХрд░рдирд╛ рд╣реИред



рдкреНрд░рд╛рд░рдВрдн рдореЗрдВ, рдореИрдВ рдпрд╣ рдХрд╣рддреЗ рд╣реБрдП рдПрдХ рд▓реЗрдЦ рд▓рд┐рдЦрдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛ рдХрд┐ iOS 10 рдкрд░ рдПрдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ UIViewPropertyAnimator рджрд┐рдЦрд╛рдИ рджрд┐рдпрд╛ рдЬреЛ рдмрд╛рдзрд┐рдд рдПрдирд┐рдореЗрд╢рди рдХреА рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рддрд╛ рд╣реИред рдЕрдм рдЙрдиреНрд╣реЗрдВ рд░реЛрдХрд╛, рдЙрд▓рдЯрд╛, рдЬрд╛рд░реА рдпрд╛ рд░рджреНрдж рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред Apple рдЗрд╕ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рджреНрд░рд╡ рдХрд╣рддрд╛ рд╣реИред

рд▓реЗрдХрд┐рди рддрдм рдореБрдЭреЗ рдПрд╣рд╕рд╛рд╕ рд╣реБрдЖ: рдЗрди рд╕рдВрдХреНрд░рдордгреЛрдВ рдХреЛ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдПрдирд┐рдореЗрдЯреЗрдб рдХреИрд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛рдП, рдЗрд╕рдХрд╛ рд╡рд░реНрдгрди рдХрд┐рдП рдмрд┐рдирд╛ рдирд┐рдпрдВрддреНрд░рдХреЛрдВ рдХреЗ рдПрдиреАрдореЗрд╢рди рдХреЛ рдмрд╛рдзрд┐рдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░рдирд╛ рдореБрд╢реНрдХрд┐рд▓ рд╣реИред рдЗрд╕рд▓рд┐рдП, рджреЛ рд▓реЗрдЦ рд╣реЛрдВрдЧреЗред рдЗрд╕рдореЗрдВ, рд╣рдо рдпрд╣ рдкрддрд╛ рд▓рдЧрд╛рдПрдВрдЧреЗ рдХрд┐ рд╕реНрдХреНрд░реАрди рдХреЛ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдХреИрд╕реЗ рджрд┐рдЦрд╛рдирд╛ рдФрд░ рдЫрд┐рдкрд╛рдирд╛ рд╣реИ, рдФрд░ рдЕрдЧрд▓реЗ рдореЗрдВ рд░реБрдХрд╛рд╡рдЯ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВред

рд╡реЗ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВ?


UIViewController рдореЗрдВ рдПрдХ UIViewController рд╕рдВрдкрддреНрддрд┐ рд╣реИред рдпрд╣ рд╡рд┐рднрд┐рдиреНрди рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рд╣реИ, рдкреНрд░рддреНрдпреЗрдХ рдПрдХ рд╡рд╕реНрддреБ рд▓реМрдЯрд╛рддрд╛ рд╣реИ:


  • animationController рд▓рд┐рдП,
  • interactionController рдХрдВрдЯреНрд░реЛрд▓рд░ рдПрдирд┐рдореЗрд╢рди рдореЗрдВ рджрдЦрд▓ interactionController рд▓рд┐рдП,
  • presentationController рдлреЙрд░ рдбрд┐рд╕реНрдкреНрд▓реЗ: рдкрджрд╛рдиреБрдХреНрд░рдо, рдлреНрд░реЗрдо рдЖрджрд┐ред


рдЗрди рд╕рднреА рдХреЗ рдЖрдзрд╛рд░ рдкрд░, рд╣рдо рдПрдХ рдкреЙрдкрдЕрдк рдкреИрдирд▓ рдмрдирд╛рдПрдВрдЧреЗ:



рдкрд╛рдХ рдХрд▓рд╛ рдирд┐рдпрдВрддреНрд░рдХ


рдЖрдк рдореЛрдбрд▓ рдирд┐рдпрдВрддреНрд░рдХреЛрдВ рдФрд░ UINavigationController ( UINavigationControllerDelegate рдорд╛рдзреНрдпрдо рд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ) рдХреЗ рд▓рд┐рдП рд╕рдВрдХреНрд░рдордг рдХреЛ рдЪреЗрддрди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рд╣рдо рдореЛрдбрд▓ рдЯреНрд░рд╛рдВрдЬрд╝рд┐рд╢рди рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВрдЧреЗред рд╢реЛ рд╕реЗ рдкрд╣рд▓реЗ рдирд┐рдпрдВрддреНрд░рдХ рд╕реЗрдЯрдЕрдк рдереЛрдбрд╝рд╛ рдЕрд╕рд╛рдорд╛рдиреНрдп рд╣реИ:


 class ParentViewController: UIViewController { private let transition = PanelTransition() // 1 @IBAction func openDidPress(_ sender: Any) { let child = ChildViewController() child.transitioningDelegate = transition // 2 child.modalPresentationStyle = .custom // 3 present(child, animated: true) } } 

  1. рдПрдХ рд╡рд╕реНрддреБ рдмрдирд╛рдПрдВ рдЬреЛ рд╕рдВрдХреНрд░рдордг рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддреА рд╣реИред transitioningDelegate рдХреЛ weak рдХреЗ рд░реВрдк transitioningDelegate рдЪрд┐рд╣реНрдирд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЖрдкрдХреЛ strong рд▓рд┐рдВрдХ рджреНрд╡рд╛рд░рд╛ transition рдЕрд▓рдЧ рд╕реЗ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред
  2. рд╣рдордиреЗ рдЕрдкрдирд╛ рдкрд░рд┐рд╡рд░реНрддрди рдЯреНрд░рд╛рдВрд╕реНрдлрд╝реЙрд░реНрдорд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рд╕реЗрдЯ рдХрд┐рдпрд╛ред
  3. presentationController .custom рдореЗрдВ рдбрд┐рд╕реНрдкреНрд▓реЗ рд╡рд┐рдзрд┐ рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдкрдХреЛ .custom рд▓рд┐рдП modalPresentationStyle. рдХреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ modalPresentationStyle. ред

рджрд┐рдЦрд╛рдП рдЧрдП рдирд┐рдпрдВрддреНрд░рдХ рдХреЛ рдпрд╣ рдирд╣реАрдВ рдкрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдХреИрд╕реЗ рджрд┐рдЦрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИред рдФрд░ рд╡рд╣ рдЕрдЪреНрдЫрд╛ рд╣реИред


рдЖрдзреА рд╕реНрдХреНрд░реАрди рдореЗрдВ рджрд┐рдЦрд╛


рдХреЗ PanelTransition рдХреЛрдб рдХреЛ presentationController рд╕рд╛рде рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВред рдпрджрд┐ рдЖрдкрдиреЗ UIPopoverController рдорд╛рдзреНрдпрдо рд╕реЗ рдкреЙрдк-рдЕрдк рдмрдирд╛рдпрд╛ рд╣реИ рддреЛ рдЖрдкрдиреЗ рдЗрд╕рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд┐рдпрд╛ рд╣реИред PresentationController рдХрдВрдЯреНрд░реЛрд▓рд░ рдХрдВрдЯреНрд░реЛрд▓рд░ рдХреЗ рдбрд┐рд╕реНрдкреНрд▓реЗ рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рддрд╛ рд╣реИ: рдлреНрд░реЗрдо, рдкрджрд╛рдиреБрдХреНрд░рдо рдЖрджрд┐ред рд╡рд╣ рдпрд╣ рддрдп рдХрд░рддрд╛ рд╣реИ рдХрд┐ iPad рдкрд░ рдкреЙрдкрдУрд╡рд░ рдХреИрд╕реЗ рджрд┐рдЦрд╛рдпрд╛ рдЬрд╛рдП: рдХрд┐рд╕ рдлреНрд░реЗрдо рдХреЗ рд╕рд╛рде, рдмрдЯрди рдХреЗ рдХрд┐рд╕ рддрд░рдл рджрд┐рдЦрд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рд╡рд┐рдВрдбреЛ рдХреА рдкреГрд╖реНрдарднреВрдорд┐ рдореЗрдВ рдХрд▓рдВрдХ рдЬреЛрдбрд╝рддрд╛ рд╣реИ рдФрд░ рдЗрд╕рдХреЗ рдиреАрдЪреЗ рдЕрдВрдзреЗрд░рд╛ рд╣реЛрддрд╛ рд╣реИред



рд╣рдорд╛рд░реА рд╕рдВрд░рдЪрдирд╛ рд╕рдорд╛рди рд╣реИ: рд╣рдо рдкреГрд╖реНрдарднреВрдорд┐ рдХреЛ рдЧрд╣рд░рд╛ рдХрд░ рджреЗрдВрдЧреЗ, рдлреНрд░реЗрдо рдХреЛ рдкреВрд░реНрдг рд╕реНрдХреНрд░реАрди рдореЗрдВ рдирд╣реАрдВ рдбрд╛рд▓реЗрдВрдЧреЗ:



presentationController(forPresented:, presenting:, source:) рд╡рд┐рдзрд┐ рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, PresentationController рд▓реМрдЯрд╛рдПрдВ:


 class PanelTransition: NSObject, UIViewControllerTransitioningDelegate { func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? { return presentationController = PresentationController(presentedViewController: presented, presenting: presenting ?? source) } 

3 рдирд┐рдпрдВрддреНрд░рдХ рдХреНрдпреЛрдВ рдкреНрд░реЗрд╖рд┐рдд рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ рдФрд░ рд╕реНрд░реЛрдд рдХреНрдпрд╛ рд╣реИ?

Source рдирд┐рдпрдВрддреНрд░рдХ рд╣реИ рдЬрд┐рд╕ рдкрд░ рд╣рдордиреЗ рд╢реЛ рдХрд╛ рдПрдиреАрдореЗрд╢рди рдХрд╣рд╛ рдерд╛ред рд▓реЗрдХрд┐рди рдЬреЛ рдирд┐рдпрдВрддреНрд░рдХ рдХрд┐рд╢реНрдд рдореЗрдВ рднрд╛рдЧ рд▓реЗрдЧрд╛, рд╡рд╣ рдкрд╣рд▓реЗ рд╕реЗ definesPresentationContext = true рдкрджрд╛рдиреБрдХреНрд░рдо рдХреЗ рд╕рд╛рде рдкрджрд╛рдиреБрдХреНрд░рдо рдореЗрдВ рд╣реИ definesPresentationContext = true ред рдпрджрд┐ рдирд┐рдпрдВрддреНрд░рдХ рдмрджрд▓ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдЕрд╕рд▓реА рд╕рдВрдХреЗрдд рдирд┐рдпрдВрддреНрд░рдХ presenting. рдкреИрд░рд╛рдореАрдЯрд░ рдореЗрдВ рд╣реЛрдЧрд╛ presenting.


рдЕрдм рдЖрдк PresentationController рд╡рд░реНрдЧ рдХреЛ рд▓рд╛рдЧреВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рд╢реБрд░реБрдЖрдд рдХреЗ рд▓рд┐рдП, рдЖрдЗрдП рднрд╡рд┐рд╖реНрдп рдХреЗ рдирд┐рдпрдВрддреНрд░рдХ рдХреЛ рдлреНрд░реЗрдо рдХрд░реЗрдВред рдЗрд╕рдХреЗ рд▓рд┐рдП рдПрдХ frameOfPresentedViewInContainerView рдкрджреНрдзрддрд┐ рд╣реИред рдирд┐рдпрдВрддреНрд░рдХ рд╕реНрдХреНрд░реАрди рдХреЗ рдирд┐рдЪрд▓реЗ рдЖрдзреЗ рд╣рд┐рд╕реНрд╕реЗ рдкрд░ рдХрдмреНрдЬрд╛ рдХрд░рддреЗ рд╣реИрдВ:


 class PresentationController: UIPresentationController { override var frameOfPresentedViewInContainerView: CGRect { let bounds = containerView!.bounds let halfHeight = bounds.height / 2 return CGRect(x: 0, y: halfHeight, width: bounds.width, height: halfHeight) } } 

рдЖрдк рдкрд░рд┐рдпреЛрдЬрдирд╛ рд╢реБрд░реВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рд╕реНрдХреНрд░реАрди рджрд┐рдЦрд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдХреБрдЫ рднреА рдирд╣реАрдВ рд╣реЛрдЧрд╛ред рдЗрд╕рдХрд╛ рдХрд╛рд░рдг рдпрд╣ рд╣реИ рдХрд┐ рдЕрдм рд╣рдо рдкрджрд╛рдиреБрдХреНрд░рдо рдХреЛ рд╕реНрд╡рдпрдВ рджреЗрдЦрддреЗ рд╣реИрдВ рдФрд░ рд╣рдореЗрдВ рдирд┐рдпрдВрддреНрд░рдХ рджреГрд╢реНрдп рдХреЛ рд╕реНрд╡рдпрдВ рдЬреЛрдбрд╝рдирд╛ рд╣реЛрдЧрд╛:


 // PresentationController.swift override func presentationTransitionWillBegin() { super.presentationTransitionWillBegin() containerView?.addSubview(presentedView!) } 

presentedView рджреГрд╢реНрдп рдХреЗ рд▓рд┐рдП рдЕрднреА рднреА рдПрдХ рдлреНрд░реЗрдо рд▓рдЧрд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред containerViewDidLayoutSubviews рд╕рдмрд╕реЗ рдЕрдЪреНрдЫреА рдЬрдЧрд╣ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕ рддрд░рд╣ рд╣рдо рд╕реНрдХреНрд░реАрди рд░реЛрдЯреЗрд╢рди рдХрд╛ рдЬрд╡рд╛рдм рджреЗ рд╕рдХрддреЗ рд╣реИрдВ:


 // PresentationController.swift override func containerViewDidLayoutSubviews() { super.containerViewDidLayoutSubviews() presentedView?.frame = frameOfPresentedViewInContainerView } 

рдЕрдм рдЖрдк рджреМрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВред рдПрдиреАрдореЗрд╢рди UIModalTransitionStyle.coverVertical рд▓рд┐рдП рдорд╛рдирдХ рд╣реЛрдЧрд╛, рд▓реЗрдХрд┐рди рдлреНрд░реЗрдо рдХрд╛ рдЖрдХрд╛рд░ рдЖрдзрд╛ рд╣реЛрдЧрд╛ред


рдкреГрд╖реНрдарднреВрдорд┐ рдХреЛ рдЧрд╣рд░рд╛ рдХрд░реЛ


рдЕрдЧрд▓рд╛ рдХрд╛рдо рдкреГрд╖реНрдарднреВрдорд┐ рдирд┐рдпрдВрддреНрд░рдХ рдХреЛ рдХрд╛рд▓рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣реИ рдЬреЛ рджрд┐рдЦрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ рдЙрд╕ рдкрд░ рдзреНрдпрд╛рди рдХреЗрдВрджреНрд░рд┐рдд рдХрд░реЗрдВред


рд╣рдо PresentationController рд╕реЗ рдЗрдирд╣реЗрд░рд┐рдЯ рдХрд░реЗрдВрдЧреЗ рдФрд░ рдЗрд╕реЗ PanelTransition рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдПрдХ рдирдП рд╡рд░реНрдЧ рдХреЗ рд╕рд╛рде рдмрджрд▓ PanelTransition ред рдирдИ рдХрдХреНрд╖рд╛ рдореЗрдВ рдХреЗрд╡рд▓ рдбрд┐рдорд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рдПрдХ рдХреЛрдб рд╣реЛрдЧрд╛ред


 class DimmPresentationController: PresentationController 

рдПрдХ рджреГрд╢реНрдп рдмрдирд╛рдПрдВ рдЬрд┐рд╕реЗ рд╣рдо рд╢реАрд░реНрд╖ рдкрд░ рдУрд╡рд░рд▓реЗ рдХрд░реЗрдВрдЧреЗ:


 private lazy var dimmView: UIView = { let view = UIView() view.backgroundColor = UIColor(white: 0, alpha: 0.3) view.alpha = 0 return view }() 

рд╣рдо рдЯреНрд░рд╛рдВрд╕реНрдлрд╝реЙрд░реНрдореЗрд╢рди рдПрдиреАрдореЗрд╢рди рдХреЗ рдЕрдиреБрд╕рд╛рд░ alpha рд╡рд┐рдЪрд╛рд░ рдмрджрд▓ рджреЗрдВрдЧреЗред 4 рд╡рд┐рдзрд┐рдпрд╛рдБ рд╣реИрдВ:


  • presentationTransitionWillBegin
  • presentationTransitionDidEnd
  • dismissalTransitionWillBegin
  • dismissalTransitionDidEnd

рдкрд╣рд▓рд╛ рд╕рдмрд╕реЗ рдХрдард┐рди рд╣реИред рдкрджрд╛рдиреБрдХреНрд░рдо рдореЗрдВ dimmView рдЬреЛрдбрд╝реЗрдВ, рдлреНрд░реЗрдо рдиреАрдЪреЗ рд░рдЦреЗрдВ рдФрд░ рдПрдиреАрдореЗрд╢рди рд╢реБрд░реВ рдХрд░реЗрдВ:


 override func presentationTransitionWillBegin() { super.presentationTransitionWillBegin() containerView?.insertSubview(dimmView, at: 0) performAlongsideTransitionIfPossible { [unowned self] in self.dimmView.alpha = 1 } } 

рдПрдиреАрдореЗрд╢рди рдХреЛ рдПрдХ рд╕рд╣рд╛рдпрдХ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд▓реЙрдиреНрдЪ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:


 private func performAlongsideTransitionIfPossible(_ block: @escaping () -> Void) { guard let coordinator = self.presentedViewController.transitionCoordinator else { block() return } coordinator.animate(alongsideTransition: { (_) in block() }, completion: nil) } 

рд╣рдордиреЗ containerViewDidLayoutSubviews dimmView рдореЗрдВ dimmView рд▓рд┐рдП рдлреНрд░реЗрдо рд╕реЗрдЯ рдХрд┐рдпрд╛


 override func containerViewDidLayoutSubviews() { super.containerViewDidLayoutSubviews() dimmView.frame = containerView!.frame } 

рдПрдиреАрдореЗрд╢рди рдХреЛ рдмрд╛рдзрд┐рдд рдФрд░ рд░рджреНрдж рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдФрд░ рдпрджрд┐ рд░рджреНрдж рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ dimmView рдХреЛ рдкрджрд╛рдиреБрдХреНрд░рдо рд╕реЗ рд╣рдЯрд╛ рджрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП:


 override func presentationTransitionDidEnd(_ completed: Bool) { super.presentationTransitionDidEnd(completed) if !completed { self.dimmView.removeFromSuperview() } } 

рдЫрд┐рдкрд╛рдиреЗ рдХреЗ рддрд░реАрдХреЛрдВ рдореЗрдВ рд░рд┐рд╡рд░реНрд╕ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рд╢реБрд░реВ рд╣реЛрддреА рд╣реИред рд▓реЗрдХрд┐рди рдЕрдм рдЖрдкрдХреЛ рдХреЗрд╡рд▓ dimmView рдХреЛ рд╣рдЯрд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдпрджрд┐ рдПрдиреАрдореЗрд╢рди рдкреВрд░рд╛ рд╣реЛ рдЧрдпрд╛ рд╣реИред


 override func dismissalTransitionWillBegin() { super.dismissalTransitionWillBegin() performAlongsideTransitionIfPossible { [unowned self] in self.dimmView.alpha = 0 } } override func dismissalTransitionDidEnd(_ completed: Bool) { super.dismissalTransitionDidEnd(completed) if completed { self.dimmView.removeFromSuperview() } } 

рдЕрдм рдмреИрдХрдЧреНрд░рд╛рдЙрдВрдб рдбрд┐рдорд┐рдВрдЧ рд╣реЛ рд░рд╣рд╛ рд╣реИред


рд╣рдо рдПрдиреАрдореЗрд╢рди рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВ


рд╣рдо рдиреАрдЪреЗ рд╕реЗ рдХрдВрдЯреНрд░реЛрд▓рд░ рджрд┐рдЦрд╛рддреЗ рд╣реИрдВ


рдЕрдм рд╣рдо рдирд┐рдпрдВрддреНрд░рдХ рдХреА рдЙрдкрд╕реНрдерд┐рддрд┐ рдХреЛ рдЪреЗрддрди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред PanelTransition рдХреНрд▓рд╛рд╕ рдореЗрдВ, PanelTransition рдХреНрд▓рд╛рд╕ PanelTransition рдЬреЛ рдЙрдкрд╕реНрдерд┐рддрд┐ рдПрдиреАрдореЗрд╢рди рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░реЗрдЧрд╛:


 func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? { return PresentAnimation() } 

рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рд╕рд░рд▓ рд╣реИ:


 extension PresentAnimation: UIViewControllerAnimatedTransitioning { func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { return duration } func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { let animator = self.animator(using: transitionContext) animator.startAnimation() } func interruptibleAnimator(using transitionContext: UIViewControllerContextTransitioning) -> UIViewImplicitlyAnimating { return self.animator(using: transitionContext) } } 

рдХреБрдВрдЬреА рдХреЛрдб рдереЛрдбрд╝рд╛ рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рд╣реИ:


 class PresentAnimation: NSObject { let duration: TimeInterval = 0.3 private func animator(using transitionContext: UIViewControllerContextTransitioning) -> UIViewImplicitlyAnimating { // transitionContext.view    ,   let to = transitionContext.view(forKey: .to)! let finalFrame = transitionContext.finalFrame(for: transitionContext.viewController(forKey: .to)!) //   ,     PresentationController //      to.frame = finalFrame.offsetBy(dx: 0, dy: finalFrame.height) let animator = UIViewPropertyAnimator(duration: duration, curve: .easeOut) { to.frame = finalFrame //   ,     } animator.addCompletion { (position) in //  ,      transitionContext.completeTransition(!transitionContext.transitionWasCancelled) } return animator } } 

IOS 9 рдореЗрдВ UIViewPropertyAnimator рдХрд╛рдо рдирд╣реАрдВ рдХрд░ рд░рд╣рд╛ рд╣реИ

рд╡рд░реНрдХрдЕрд░рд╛рдЙрдВрдб рдХрд╛рдлреА рд╕рд░рд▓ рд╣реИ: рдЖрдкрдХреЛ animateTransition рдХреЛрдб рдореЗрдВ рдПрдирд┐рдореЗрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдкреБрд░рд╛рдиреЗ UIView.animateтАж api UIView.animateтАж рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЬреИрд╕реЗ:


 func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { let to = transitionContext.view(forKey: .to)! let finalFrame = transitionContext.finalFrame(for: transitionContext.viewController(forKey: .to)!) to.frame = finalFrame.offsetBy(dx: 0, dy: finalFrame.height) UIView.animate(withDuration: duration, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 0, options: [.curveEaseOut], animations: { to.frame = finalFrame }) { (_) in transitionContext.completeTransition(!transitionContext.transitionWasCancelled) } }    ,   `interruptibleAnimator(using transitionContext:)` 

рдпрджрд┐ рдЖрдк рдПрдХ рд░реБрдХрд╛рд╡рдЯ рдирд╣реАрдВ рдмрдирд╛рддреЗ рд╣реИрдВ, рддреЛ рд░реБрдХрд╛рд╡рдЯрдирд┐рдореНрдиреЗрдЯрд░ рд╡рд┐рдзрд┐ рдХреЛ рдЫреЛрдбрд╝рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдЕрдЧрд▓реЗ рд▓реЗрдЦ рдореЗрдВ рд╕рджрд╕реНрдпрддрд╛ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред


рдирд┐рдпрдВрддреНрд░рдХ рдХреЛ рдЫрд┐рдкрд╛рдПрдВ


рд╕рдм рдХреБрдЫ рдПрдХ рд╣реА рд╣реИ, рдХреЗрд╡рд▓ рд╡рд┐рдкрд░реАрдд рджрд┐рд╢рд╛ рдореЗрдВред Panel Transition DismissAnimation рдХреНрд▓рд╛рд╕ рдмрдирд╛рдПрдБ:


 func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { return DismissAnimation() } 

рдФрд░ рд╣рдореЗрдВ рдЗрд╕рдХрд╛ рдПрд╣рд╕рд╛рд╕ рд╣реИред DismissAnimation рдХрдХреНрд╖рд╛:


 class DismissAnimation: NSObject { let duration: TimeInterval = 0.3 private func animator(using transitionContext: UIViewControllerContextTransitioning) -> UIViewImplicitlyAnimating { let from = transitionContext.view(forKey: .from)! let initialFrame = transitionContext.initialFrame(for: transitionContext.viewController(forKey: .from)!) let animator = UIViewPropertyAnimator(duration: duration, curve: .easeOut) { from.frame = initialFrame.offsetBy(dx: 0, dy: initialFrame.height) } animator.addCompletion { (position) in transitionContext.completeTransition(!transitionContext.transitionWasCancelled) } return animator } } extension DismissAnimation: UIViewControllerAnimatedTransitioning { func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { return duration } func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { let animator = self.animator(using: transitionContext) animator.startAnimation() } func interruptibleAnimator(using transitionContext: UIViewControllerContextTransitioning) -> UIViewImplicitlyAnimating { return self.animator(using: transitionContext) } } 

рдЗрд╕ рд╕реНрдерд╛рди рдкрд░ рдЖрдк рдкрд╛рд░реНрдЯрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рдкреНрд░рдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
- рдПрдХ рд╡реИрдХрд▓реНрдкрд┐рдХ рдкрд░рд┐рджреГрд╢реНрдп рдиреАрдЪреЗ рджрд┐рдЦрд╛рдИ рджреЗ рд╕рдХрддрд╛ рд╣реИ;
- рджрд╛рдИрдВ рдУрд░ - рддреНрд╡рд░рд┐рдд рдореЗрдиреВ рдиреЗрд╡рд┐рдЧреЗрд╢рди;
- рдКрдкрд░ - рд╕реВрдЪрдирд╛рддреНрдордХ рд╕рдВрджреЗрд╢:



рдбреЛрдбреЛ рдкрд┐рдЬреНрдЬрд╛ , рд╕реНрдиреИрдХ рдФрд░ рд╕реЗрд╡рдИ


рдЕрдЧрд▓реА рдмрд╛рд░ рд╣рдо рдПрдХ рдЗрд╢рд╛рд░рд╛ рдХреЗ рд╕рд╛рде рдПрдХ рдЗрдВрдЯрд░реИрдХреНрдЯрд┐рд╡ рд╕рдорд╛рдкрди рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ, рдФрд░ рдлрд┐рд░ рд╣рдо рдЗрд╕рдХреЗ рдПрдиреАрдореЗрд╢рди рдХреЛ рдмрд╛рдзрд┐рдд рдХрд░рддреЗ рд╣реИрдВред рдпрджрд┐ рдЖрдк рдкреНрд░рддреАрдХреНрд╖рд╛ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рддреЛ рдкреВрд░реА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЧреАрдердм рдкрд░ рд╣реИред


рдФрд░ рдпрд╣рд╛рдБ рд▓реЗрдЦ рдХрд╛ рджреВрд╕рд░рд╛ рднрд╛рдЧ рдЖрдпрд╛ред

рдбреЛрдбреЛ рдкрд┐рдЬреНрдЬрд╛ рдореЛрдмрд╛рдЗрд▓ рдЪреИрдирд▓ рдХреА рд╕рджрд╕реНрдпрддрд╛ рд▓реЗрдВ ред

Source: https://habr.com/ru/post/hi463527/


All Articles