applidium / OverlayContainer

Non-intrusive iOS UI library to implement overlay based interfaces
https://gaetanzanella.github.io/2018-12-17/replicating-apple-maps-overlay
Other
1.15k stars 94 forks source link

Could I know overlay position changes realtime #78

Closed FrankWuoO closed 3 years ago

FrankWuoO commented 3 years ago

Hi there! I'm trying to make interaction with other views in sync with the overlay transition and maybe is same issue with #42

Here is my implementation, I put detect point code in

func overlayContainerViewController(_ containerViewController: OverlayContainerViewController, willTranslateOverlay overlayViewController: UIViewController, transitionCoordinator: OverlayContainerTransitionCoordinator) {
    print("Moving")
    transitionCoordinator.animate { (context) in
    } completion: { (context) in
          let point = self.view.convert(overlayViewController.view.frame.origin, from: overlayViewController.view)
          let limit: CGFloat = kTopDistance + self.view.safeAreaInsets.top
          var offset: CGFloat = 0.0
          if point.y < limit {
              offset = limit - point.y
          }
          self.topContainerTopConstraint.constant = -offset
    }
}

It works fine with using finger to drag overlay, but when I slide up the overlay quickly or call containerVC.moveOverlay(toNotchAt: 2, animated: true), it's jump a little bit.

I checked the code and found that delegate didn't call this method overlayContainerViewController(_ containerViewController: OverlayContainerViewController, willTranslateOverlay overlayViewController: UIViewController, transitionCoordinator: OverlayContainerTransitionCoordinator) continuously

I've attached a video.

https://user-images.githubusercontent.com/10287931/103202138-93ae6280-492c-11eb-9516-84f3ac55d1d0.mov

gaetanzanella commented 3 years ago

Hi @FrankWuoO

The transitions can be animated. In that case, the delegate method will be called only once when the transition starts. You can detect them using the OverlayContainerTransitionCoordinatorContext.isAnimated property.

I would move your logic to the animate block and use the context.targetTranslationHeight property to know where the container will be instead of the current overlay position:

func overlayContainerViewController(_ containerViewController: OverlayContainerViewController, willTranslateOverlay overlayViewController: UIViewController, transitionCoordinator: OverlayContainerTransitionCoordinator) {
    transitionCoordinator.animate(alongsideTransition: { (context) in
          let offset = ... // based on `context.targetTranslationHeight`
          self.topContainerTopConstraint.constant = -offset
          if context.isAnimated {
              self.view.layoutIfNeeded() // to animate the layout update
          }
    }, completion: nil)
}
FrankWuoO commented 3 years ago

@gaetanzanella Cool!! You save my day. Thanks for your answer. 🙇