2010-07-22 28 views
5

我在UIScrollView中有UIView。每当UIScrollView缩放更改时,我想在新的缩放级别重新绘制整个UIView每次缩放后重画UIScrollView的内容

在iOS系统< 3.2,我是通过调整UIScrollViewUIView,使之成为新的大小,然后设置变换回身份,因此它不会试图进一步调整它这样做。但是,如果iOS> = 3.2,更改标识也会更改UIScrollView的zoomScale属性。

结果是,无论何时我放大(比如说2x),我都会将嵌入的UIView调整为适当的大小,然后重新绘制它。但是现在(因为我将变换重置为标识),UIScrollView认为它再次位于zoomScale 1,而不是zoomScale 2.因此,如果我将maxZoomScale设置为2,它仍会尝试进一步缩放,这是错误的。

我曾考虑过使用CATiledLayer,但我认为这对我来说不足够,因为我想在每次缩放后重新绘制,而不仅仅是像某些缩放阈值一样。

有没有人知道如何做一个缩放适当的重绘UIView

回答

15

汤姆,

你的问题是有点老了,但我想出了一个解决方案,所以我想我会放在一个答案的情况下,它可以帮助你或其他人。基本技巧是将滚动视图的zoomScale重置为1,然后调整minimumZoomScalemaximumZoomScale,以便用户仍然可以按预期放大和缩小。

在我的实现中,我已将子类UIScrollView设置为它自己的代理。在我的子类中,我实现了缩放所需的两个委托方法(如下所示)。 contentView是我添加到我的UIScrollView子类中的一个属性,用于为其提供实际显示内容的视图。

所以,我的init方法看起来是这样的(kMinimumZoomScalekMaximumZoomScale都在班上名列前茅#define的):

- (id)initWithFrame:(CGRect)frame { 
    if (self = [super initWithFrame:frame]) { 
     self.autoresizesSubviews = YES; 
     self.showsVerticalScrollIndicator = YES; 
     self.showsHorizontalScrollIndicator = NO; 
     self.bouncesZoom = YES; 
     self.alwaysBounceVertical = YES; 
     self.delegate = self; 

     self.minimumZoomScale = kMinimumZoomScale; 
     self.maximumZoomScale = kMaximumZoomScale; 
    } 

    return self; 
} 

然后我实施缩放标准UIScrollView委托方法。我的ContentView类有一个名为zoomScale的属性,告诉它用什么比例来显示其内容。它在其drawRect方法中使用该方法根据需要调整内容的大小。

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)aScrollView { 
    return contentView; 
} 


- (void)scrollViewDidEndZooming:(UIScrollView *)aScrollView withView:(UIView *)view atScale:(float)scale { 
    CGFloat oldZoomScale = contentView.zoomScale; 
    CGSize size = self.bounds.size; 

    // Figure out where the scroll view was centered so that we can 
    // fix up its offset after adjusting the scaling 
    CGPoint contentCenter = self.contentOffset; 
    contentCenter.x += size.width/(oldZoomScale * scale)/2; 
    contentCenter.y += size.height/(oldZoomScale * scale)/2; 

    CGFloat newZoomScale = scale * oldZoomScale; 
    newZoomScale = MAX(newZoomScale, kMinimumZoomscale); 
    newZoomScale = MIN(newZoomScale, kMaximumZoomscale); 

    // Set the scroll view's zoom scale back to 1 and adjust its minimum and maximum 
    // to allow the expected amount of zooming. 
    self.zoomScale = 1.0; 
    self.minimumZoomScale = kMinimumZoomScale/newZoomScale; 
    self.maximumZoomScale = kMaximumZoomScale/newZoomScale; 

    // Tell the contentView about its new scale. My contentView.zoomScale setter method 
    // calls setNeedsDisplay, but you could also call it here 
    contentView.zoomScale = newZoomScale; 

    // My ContentView class overrides sizeThatFits to give its expected size with 
    // zoomScale taken into account 
    CGRect newContentSize = [contentView sizeThatFits]; 

    // update the content view's frame and the scroll view's contentSize with the new size 
    contentView.frame = CGRectMake(0, 0, newContentSize.width, newContentSize.height); 
    self.contentSize = newContentSize; 

    // Figure out the new contentOffset so that the contentView doesn't appear to move 
    CGPoint newContentOffset = CGPointMake(contentCenter.x - size.width/newZoomScale/2, 
              contentCenter.y - size.height/newZoomScale/2); 
    newContentOffset.x = MIN(newContentOffset.x, newContentSize.width - size.width); 
    newContentOffset.x = MAX(0, newContentOffset.x); 
    newContentOffset.y = MIN(newContentOffset.y, newContentSize.height - .size.height); 
    newContentOffset.y = MAX(0, newContentOffset.y); 
    [self setContentOffset:newContentOffset animated:NO]; 
} 
+0

非常感谢您的解决方案!这解决了[我的问题](http://stackoverflow.com/questions/3970988/how-to-draw-on-a-non-transformed-context-while-zoomed-in-a- catiledlayer)。你可以在那里留下一个链接到你的答案,所以我可以给你适当的信用来回答它? – TinkerTank 2010-10-21 14:08:37

+0

如果使用此方法缩放CATiledLayer,则在调用setNeedsDisplay之前需要清除tile-cache。清除CATiledLayerCache的解决方案可在[here](http:// stackoverflow。com/questions/1274680/clear-catiledlayers-cache-when-changing-images) – TinkerTank 2010-10-21 14:12:15

+0

你能解释一下contentSize的属性以及它如何设置以及它实际是什么。谢谢 – BDGapps 2012-03-06 03:32:40

0

在我的情况,我有一个图像视图,并在图像视图顶部我有其他几个图像视图。这是我想出的实施,并且工作正常:

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(double)scale{ 
    NSLog(@"finished zooming"); 

    NSLog(@"position x :%f",pin1.frame.origin.x); 
    NSLog(@"position y :%f",pin1.frame.origin.y); 


    CGRect frame = pin1.frame; 
    frame.origin.x = pin1.frame.origin.x * scale; 
    frame.origin.y = pin1.frame.origin.y * scale; 
    pin1.frame = frame; 

    NSLog(@"position x new :%f",pin1.frame.origin.x); 
    NSLog(@"position y new:%f",pin1.frame.origin.y); 

}