UIScrollView缩放后重新绘制子视图

3
我有一个UIScrollView,里面包含一个子UIView(CATiledLayer),然后还有更多的子视图(其中一些是UITextView)。

缩放后,所有东西都变得模糊不清。

我已经阅读了各种相关文章,它们似乎都表明我必须处理scrollViewDidEndZooming,然后“做一些变换处理、调整框架和微调内容偏移”。请问有人能解释一下这是如何工作的吗?

提前致谢...

2个回答

18

我曾遇到类似的问题,需要在文本上进行缩放。我的情况并没有使用CATiledLayer,所以这个解决方案可能适用或不适用于你。我也没有使用ARC,所以如果你正在使用,你还需要进行相应的调整。

我提出的解决方案是将UIScrollViewDelegate方法设置如下:

// Return the view that you want to zoom. My UIView is named contentView.
-(UIView*) viewForZoomingInScrollView:(UIScrollView*)scrollView {
  return self.contentView;
}

// Recursively find all views that need scaled to prevent blurry text
-(NSArray*)findAllViewsToScale:(UIView*)parentView {
    NSMutableArray* views = [[[NSMutableArray alloc] init] autorelease];
    for(id view in parentView.subviews) {

        // You will want to check for UITextView here. I only needed labels.
        if([view isKindOfClass:[UILabel class]]) {
            [views addObject:view];
        } else if ([view respondsToSelector:@selector(subviews)]) {
            [views addObjectsFromArray:[self findAllViewsToScale:view]];
        }
    }
    return views;
}

// Scale views when finished zooming
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale {
    CGFloat contentScale = scale * [UIScreen mainScreen].scale; // Handle retina

    NSArray* labels = [self findAllViewsToScale:self.contentView];
    for(UIView* view in labels) {
        view.contentScaleFactor = contentScale;
    }
}

1
非常非常感谢!我为了这个问题已经苦恼了好几天! - ethyreal
1
我唯一要添加的是,didEndZooming方法也会在弹跳后调用,因此最好从[scrollView zoomScale]获取比例。 - ethyreal
太好了,它帮助了我 :) - Khalid Usman
这对我来说是救命稻草,但我们需要调用 [setneedsdisplay] 吗? - anoop4real
谢谢伙计,非常好的答案。 - M Swapnil

1
我遇到了同样的问题,上面的代码对我的情况没有用。然后我按照文档进行操作:
如果您想要在滚动视图中支持缩放,则最常见的技术是使用一个子视图来包含整个内容大小的滚动视图,然后向该视图添加其他子视图。这允许您将单个“集合”内容视图指定为要缩放的视图,并且其所有子视图都将根据其状态进行缩放。 https://developer.apple.com/library/ios/#documentation/WindowsViews/Conceptual/UIScrollView_pg/CreatingBasicScrollViews/CreatingBasicScrollViews.html的“添加子视图”部分。
我简单地创建了一个空视图,并将我的CATiledLayer和所有其他子视图添加到该空视图中。然后将该空视图作为滚动视图的唯一子视图添加即可。它完美地工作了。大致如下:
- (void)viewDidLoad
{
    _containerView = [[UIView alloc] init];
    [_containerView addSubView:_yourTiledView];
    for (UIView* subview in _yourSubviews) {
        [_containerView addSubView:subview];
    }
    [_scrollView addSubView:_containerView];
}

-(UIView*) viewForZoomingInScrollView:(UIScrollView*)scrollView {
    return _containerView;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接