每次缩放后重绘UIScrollView内容 [英] Redrawing UIScrollView contents after every zoom

查看:310
本文介绍了每次缩放后重绘UIScrollView内容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 UIScrollView 中有 UIView 。每当 UIScrollView 缩放更改时,我想以新的缩放级别重绘整个 UIView

I have a UIView inside a UIScrollView. Whenever the UIScrollView zoom changes, I want to redraw the entire UIView at the new zoom level.

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

In iOS < 3.2, I was doing this by resizing the UIView within the UIScrollView to make it the new size, and then setting the transform back to Identity, so that it wouldn't try to resize it further. However, with iOS >= 3.2, changing the identity also changes the UIScrollView's zoomScale property.

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

The result is that whenever I zoom (say 2x), I adjust the embedded UIView to be the appropriate size, and redraw it. However now (since I reset the transform to Identity), the UIScrollView thinks its once again at zoomScale 1, rather than zoomScale 2. So if I have my maxZoomScale set at 2, it will still try zooming further, which is wrong.

我想过使用 CATiledLayer ,但我不知道我认为这对我来说已经足够了,因为我想在每次缩放后重绘,而不是像它试图那样在某些缩放阈值下重绘。

I thought about using the CATiledLayer, but I don't think this is sufficient for me, since I want to redraw after every zoom, not just at certain zoom thresholds like it tries to do.

有谁知道怎么做在缩放时正确地重新绘制 UIView

Does anyone know how to do the proper redrawing of the UIView on a zoom?

推荐答案

汤姆,

你的问题有点陈旧,但我想出了一个解决方案,所以我想我会给你一个答案,以防它或其他任何人帮助你。基本技巧是将滚动视图的 zoomScale 重置为1,然后调整 minimumZoomScale maximumZoomScale 这样用户仍然可以按预期放大和缩小。

Your question is a bit old, but I came up with a solution for this, so I figured I'd put in an answer in case it helps you or anyone else. The basic trick is to reset the scroll view's zoomScale to 1, and then adjust the minimumZoomScale and maximumZoomScale so that the user can still zoom in and out as expected.

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

In my implementation, I've subclassed UIScrollView and set it to be its own delegate. In my subclass, I implement the two delegate methods you need for zooming (shown below). contentView is a property I added to my UIScrollView subclass that in order to give it the view that actually displays the content.

所以,我的init方法看起来像这样( kMinimumZoomScale kMaximumZoomScale #define 位于班级顶部):

So, my init method looks something like this (kMinimumZoomScale and kMaximumZoomScale are #define's at the top of the class):

- (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 方法中使用它来根据需要调整内容的大小。

Then I implement the standard UIScrollView delegate methods for zooming. My ContentView class has a property called zoomScale that tells it what scale to use for displaying its content. It uses that in its drawRect method to resize the content as appropriate.

- (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];
}

这篇关于每次缩放后重绘UIScrollView内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆