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