1

Is there a way to limit the effect of UIPercentDrivenInteractiveTransition to only the topmost view in a view hierarchy?

Specifically: as explained here and here the interactive transition sets the container view layer's speed to 0 and then manipulates the timeOffset to scrub through the transition.

If for example I have an activity indicator in that containing view, the interactive transition also scrubs through the activity indicator's spin animation. It stops spinning and appears to "roll" forward and back with the interactive transition.

Is there a way to localize the effect of setting speed and timeOffset and prevent them from propagating through to any or all subviews?

So far, I can think of two possible approaches:

  1. Create a "barrier" layer: subclass CALayer and override setTimeOffset: to prevent or selectively prevent changes

  2. Subclass or replace UIPercentDrivenInteractiveTransition with something that traverses the subview hierarchy and selectively hits only certain views

Any other ideas would be welcome.

Community
  • 1
  • 1
bcattle
  • 12,115
  • 6
  • 62
  • 82

3 Answers3

1

You should tell the activity animator to stop animating, but keep it visible, during the transition. This is consistent with how Apple handles this in its apps. For example, in the Mail app, do pull-to-refresh to get new messages. While the indicator is spinning, use the interactive pop gesture recognizer to about halfway. Notice that the activity indicator stops during the interactive transition.

Aaron Brager
  • 65,323
  • 19
  • 161
  • 287
  • I like this proposal too. If the OP doesn't want to hide the animator, he can just stop the animation for the duration of the transition. – matt Jan 07 '15 at 02:25
  • This is a good suggestion, and it's awesome that you get this behavior (time synchronization) for free, but I'd hoped this question would be a little more general. For example you might not want an AVPlayerLayer to scrub, but currently the propagating `timeOffset` does so. – bcattle Jan 07 '15 at 02:50
0

Why don't you just hide the activity indicator for the duration of the animation? Surely it has no purpose being there, has it? After all, it cannot mean "animation is in progress" - the user does not sense this as an animation, or even as a time-consuming transition, but as a gesture being driven by a finger. You can easily show it again when the animation is over, by using the animation's completion handler.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • Good thought. In this case though it means "network traffic in progress" and you're hiding it to cancel the operation. Ideally you could change your mind until you lift your finger and the transition completes. – bcattle Jan 07 '15 at 01:37
  • It is not supposed to mean that. If network traffic is in progress, use UIApplication's `networkActivityIndicatorVisible` - that is what it's for. – matt Jan 07 '15 at 01:40
  • Agreed. In this case it's showing that a specific image is loading of several – bcattle Jan 07 '15 at 01:41
  • But I would still argue that it is not your job to show the user this fact using a spinner _during the gesture_. The user is busy. You don't have to be showing that the app is also busy. – matt Jan 07 '15 at 01:42
  • Hmmm that's a good point. I was more going for the "seamless" interactive transition experience but philosophically you're right. – bcattle Jan 07 '15 at 02:06
0

The answer to this question is no. According to Apple, the CALayer class adopts CAMediaTiming "allowing a layer to define a timespace relative to its superlayer". In other words, whatever values of timeOffset or beginTime are specified in a child layer are summed with the layers above. As the docs state, "This concept of a layer-tree timespace provides a scalable timeline that starts at the root layer, through its descendants."

The UIPercentDrivenInteractiveTransition acts by scrubbing through the timeOffset of [transitionContext containerView].layer. (transitionContext is an id<UIViewControllerContextTransitioning>).

Therefore it is applying a time offset that is then automatically adopted by all child layers down the sublayer chain.

There is no such thing as a "barrier" or "selectively hitting only certain layers" because this time propagation is handled by Core Animation internally.

bcattle
  • 12,115
  • 6
  • 62
  • 82