每次缩放后重绘 UIScrollView 内容

Redrawing UIScrollView contents after every zoom(每次缩放后重绘 UIScrollView 内容)

本文介绍了每次缩放后重绘 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.

结果是每当我缩放(比如 2 倍)时,我都会将嵌入的 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,然后调整 minimumZoomScalemaximumZoomScale 以便用户仍然可以放大和正如预期的那样.

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 方法看起来像这样(kMinimumZoomScalekMaximumZoomScale#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 内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本文标题为:每次缩放后重绘 UIScrollView 内容

基础教程推荐