In iOS 4.0, why does UIScrollView zoomToRect:animated: not trigger the scrollViewDidScroll or scrollViewDidZoom delegates while animating?

[亡魂溺海] 提交于 2019-11-28 19:12:11

Brutal but works.

Define some properties:

@property (nonatomic, strong) UIView *zoomedView;    
@property (nonatomic, strong) CADisplayLink *displayLink;
@property (nonatomic) CGFloat currentScale;

Inform UIScrollView which UIView is going to be zoomed:

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
     return self.zoomedView;
}

Register for a CADisplayLink ticks. It runs Core Animation as well, so it will be kicked on same intervals:

self.displayLink  = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkTick)];
[self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

Check zoomedView's presentationLayer for current values.

- (void)displayLinkTick
{
    CALayer *zoomedLayer = self.zoomedView.layer.presentationLayer;
    CGFloat scale = zoomedLayer.transform.m11;

    if (scale != self.currentScale) {
         self.currentScale = scale; // update property

         // the scale has changed!
    }
}
fishinear

In IOS 4.0, animations are done by the OS - I assume to make use of GPU based hardware acceleration as much as possible. As a disadvantage of that, it becomes harder to animate a values that is derived from another (animated) value. As in your case, the positions of the subviews that depend on the zoom level of the UIScrollView. In order to make that happen, you should setup the animation of the subviews to go in parallel with the animation of the zooming. Try something like:

[UIView animateWithDuration:0.5 delay:0
                    options:UIViewAnimationOptionLayoutSubviews
                 animations:^{
    theScrollView.zoomScale = zoomScale;
    // layout the subviews here
} completion:^(BOOL finished) {}];

This should set the frame properties of the subviews from within the same animation context, and therefore, they should be animated together by the OS.

See also the answers to this question: How to make UIScrollView send scrollViewDidScroll messages during animations

Is it viable to update all the subviews within an animation block (or begin/commitAnimation)? Something like:

[self zoomToRect:zoomRect animated:YES];
[UIView animateWithDuration:1.0
    animations:^ {
        // change your subviews
    }
];
Binyamin Bauman

Register for KVO of the zoomScale property of the UIScrollView after you call zoomToRect:animated:.

[scrollView addObserver:self
            forKeyPath:@"zoomScale"
               options:(NSKeyValueObservingOptionNew |
                        NSKeyValueObservingOptionOld)
                context:NULL];

Then, implement this method:

- (void)observeValueForKeyPath:(NSString *)keyPath
              ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context
{
    if ([keyPath isEqual:@"zoomScale"]) {
    // use the new zoomScale value stored
    // in the NSKeyValueChangeNewKey change
    // dictionary key  to resize your subviews
    }
    // be sure to call the super implementation
    // if the superclass implements it
    [super observeValueForKeyPath:keyPath
                ofObject:object
                 change:change
                 context:context];
}

Check out the KVO documentation.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!