问题描述
我在 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内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!