每次缩放后重绘UIScrollView内容

时间:2010-07-22 22:16:26

标签: iphone uiscrollview ios

UIView内有UIScrollView。每当UIScrollView缩放发生变化时,我想以新的缩放级别重绘整个UIView

在iOS< 3.2,我这样做是通过调整UIView中的UIScrollView来使其成为新的大小,然后将转换设置回Identity,这样它就不会尝试进一步调整它。但是,对于iOS> = 3.2,更改标识也会更改UIScrollView的zoomScale属性。

结果是每当我缩放(比如2x)时,我都会将嵌入的UIView调整为合适的大小,然后重新绘制它。但是现在(因为我将转换重置为Identity),UIScrollView再次认为它是zoomScale 1而不是zoomScale 2.所以如果我将maxZoomScale设置为2,它仍然会尝试进一步缩放,这是错。

我考虑过使用CATiledLayer,但我不认为这对我来说已经足够了,因为我希望在每次缩放后重绘,而不是像某些缩放阈值那样重绘。

有人知道如何在缩放时正确重绘UIView吗?

2 个答案:

答案 0 :(得分: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];
}

答案 1 :(得分: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);

}