UIScrollView zoomToRect没有缩放到给定的rect(从UITouch CGPoint创建)

时间:2010-03-05 02:22:39

标签: iphone uiscrollview calayer

我的应用程序有一个带有一个子视图的UIScrollView。子视图是一个扩展的UIView,它使用drawLayer事件中的图层将PDF页面打印到自身。

使用内置捏合进行缩放效果很好。 setZoomScale也可以按预期工作。

我一直在努力使用zoomToRect功能。我发现了一个在线示例,它从给定的CGPoint生成CGRect zoomRect变量。

在touchesEnded函数中,如果有双击并且它们一直缩小,我想放大到我创建的PDFUIView,好像它们正在用它们双击的夹点中心捏出来。

因此,假设我将UITouch变量传递给我的函数,如果它们双击,则使用zoomToRect。

我开始使用我在苹果网站上找到的以下功能:

http://developer.apple.com/iphone/library/documentation/WindowsViews/Conceptual/UIScrollView_pg/ZoomZoom/ZoomZoom.html

以下是我的UIScrollView扩展类的修改版本:

- (void)zoomToCenter:(float)scale withCenter:(CGPoint)center {     

    CGRect zoomRect;
    zoomRect.size.height = self.frame.size.height / scale;
    zoomRect.size.width  = self.frame.size.width  / scale;

    zoomRect.origin.x = center.x - (zoomRect.size.width  / 2.0);
    zoomRect.origin.y = center.y - (zoomRect.size.height / 2.0); 

    //return zoomRect;

    [self zoomToRect:zoomRect animated:YES];

} 

当我这样做时,UIScrollView似乎使用上面的zoomRect的右下边缘而不是中心进行缩放。

如果我像这样制作UIView

UIView *v = [[UIView alloc] initWithFrame:zoomRect]; 
[v setBackgroundColor:[UIView redColor]];
[self addSubview:v];

红色框显示触摸点位于中心位置。

请注意:我正在从我的电脑上写这篇文章,我记得在我的Mac上用两部分分开,所以假设这画了一个矩形,触点在中心。如果UIView离开中心但是缩小到正确的位置那将是好事。

但是,当它预先形成zoomToRect时,它似乎使用了放大结果左上角的zoomRect右下角。

另外,我注意到,根据我点击UIScrollView的位置,它会锚定到不同的位置。几乎看起来中间有一个交叉点,它以某种方式反映了点,好像中间的任何一个点都是负反射,中间的任何地方都是正反射?

这似乎很复杂,不应该只是缩放到UIView能够绘制的绘制的矩形吗?

我使用了大量的研究来弄清楚如何创建一个高质量的PDF,所以我假设使用CALayer可能会抛弃坐标系?但是对于UIScrollView,它应该将其视为具有768x985尺寸的视图。

这有点高级,请假设创建zoomRect的代码都很好。 UIView中的CALayer有更深层次的内容,位于UIScrollView ....

9 个答案:

答案 0 :(得分:4)

好的另一个答案:

苹果提供的例程适用于我,但您需要让手势识别器将点击点转换为imageView坐标 - 而不是滚动条。

Apple的例子是这样做的,但由于我们的应用程序工作方式不同(我们更改了UIImageView),因此在uiscrollview上设置了gestureRecongnizer - 工作正常,但你需要在handleDoubleTap中执行此操作:

这基于苹果示例代码“TaptoZoom”,但正如我所说,我们需要将手势识别器连接到滚动视图。

- (void)handleDoubleTap:(UIGestureRecognizer *)gestureRecognizer {
    // double tap zooms in
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(handleSingleTap:) object:nil];
    float newScale = [imageScrollView zoomScale] * 1.5;
    // Note we need to get location of the tap in the imageView coords, not the imageScrollView
    CGRect zoomRect = [self zoomRectForScale:newScale withCenter:[gestureRecognizer locationInView:imageView]];
    [imageScrollView zoomToRect:zoomRect animated:YES];
}

答案 1 :(得分:4)

   Declare BOOL isZoom; in .h


     -(void)handleDoubleTap:(UIGestureRecognizer *)recognizer {  
            if(isZoom){
                CGPoint Pointview=[recognizer locationInView:self];
                CGFloat newZoomscal=3.0;

                newZoomscal=MIN(newZoomscal, self.maximumZoomScale);

                CGSize scrollViewSize=self.bounds.size;

                CGFloat w=scrollViewSize.width/newZoomscal;
                CGFloat h=scrollViewSize.height /newZoomscal;
                CGFloat x= Pointview.x-(w/2.0);
                CGFloat y = Pointview.y-(h/2.0);

                CGRect rectTozoom=CGRectMake(x, y, w, h);
                [self zoomToRect:rectTozoom animated:YES]; 

                [self setZoomScale:3.0 animated:YES]; 
                isZoom=NO;
            }
            else{ 
                [self setZoomScale:1.0 animated:YES]; 
                isZoom=YES;
            }
        } 

答案 2 :(得分:1)

我注意到,如果图像以小于1的zoomScale开始,那么您使用的苹果无法正确缩放,因为zoomRect原点不正确。我编辑它才能正常工作。这是代码:

- (CGRect)zoomRectForScale:(float)scale withCenter:(CGPoint)center {

CGRect zoomRect;

// the zoom rect is in the content view's coordinates. 
//    At a zoom scale of 1.0, it would be the size of the imageScrollView's bounds.
//    As the zoom scale decreases, so more content is visible, the size of the rect grows.
zoomRect.size.height = [self frame].size.height / scale;
zoomRect.size.width  = [self frame].size.width / scale;


// choose an origin so as to get the right center.
zoomRect.origin.x = (center.x * (2 - self.minimumZoomScale) - (zoomRect.size.width  / 2.0));
zoomRect.origin.y = (center.y * (2 - self.minimumZoomScale) - (zoomRect.size.height / 2.0));

return zoomRect;
}

关键是这部分将中心值乘以(2 - self.minimumZoomScale)。 希望这会有所帮助。

答案 3 :(得分:1)

就我而言:

zoomRect.origin.x    = center.x / self.zoomScale - (zoomRect.size.width  / 2.0);
zoomRect.origin.y    = center.y / self.zoomScale  - (zoomRect.size.height / 2.0);

答案 4 :(得分:1)

扩展 UIScrollView {

func getRectForVisibleView() -> CGRect {
    var visibleRect: CGRect = .zero
    
    visibleRect.origin = self.contentOffset
    visibleRect.size = self.bounds.size

    let theScale = 1.0 / self.zoomScale
    visibleRect.origin.x *= theScale
    visibleRect.origin.y *= theScale
    visibleRect.size.width *= theScale
    visibleRect.size.height *= theScale
    
    return visibleRect
}

func moveToRect(rect: CGRect) {
    let scale = self.bounds.width / rect.width
    self.zoomScale = scale
    self.contentOffset = .init(x: rect.origin.x * scale, y: rect.origin.y * scale)
}

}

答案 5 :(得分:0)

我有类似的东西,因为我没有调整center.x和center.y值,除以它们的比例(使用center.x / scale和center.y / scale)。也许我没有正确阅读你的代码。

答案 6 :(得分:0)

我有相同的行为并且非常令人沮丧...被提供给UIScrollView的矩形是完美的..但我的观点,无论我做什么涉及以编程方式更改zoomScale总是缩放和缩放到坐标0,0,无论如何。

我尝试过只更改zoomScale,我尝试过zoomToRect,我已经尝试了所有这些,每当我在代码中触摸zoomScale时,它就会调到0,0坐标。

在缩放操作后,我还必须在scrollview中为调整大小的图像添加和显式setContentSize,否则我无法在缩放或捏合后滚动。

这是3.1.3中的错误还是什么?

答案 7 :(得分:0)

我尝试了不同的解决方案,但这看起来是最好的解决方案 这是非常直接和概念性的?

CGRect frame = [[UIScreen mainScreen] applicationFrame];
scrollView.contentInset = UIEdgeInsetsMake(frame.size.height/2,
                 frame.size.width/2,
                 frame.size.height/2,
                 frame.size.width/2); 

答案 8 :(得分:0)

我不同意上面的一条评论说你不应该将中心的坐标乘以某个因素。

假设您当前正在100x100滚动视图中显示整个400x400px图像或PDF文件,并希望允许用户将内容的大小加倍,直到达到1:1。 如果您在点(75,75)处双击,则您希望放大的矩形在新的200x200内容视图中具有原点100,100和大小100x100。所以原来的分接点(75,75)现在(150,150)在新的200x200空间内。

现在,在缩放操作#1完成后,如果再次双击(75,75)新的100x100矩形(这是较大的200x200矩形的右下角),您希望用户是显示较大图像的右下角100x100平方,现在可以缩放到400x400像素。

为了在较大的400x400矩形内计算最新100x100矩形的原点,您需要考虑比例和当前内容偏移(因为在此最后一次缩放操作之前,我们在200x200内显示右下角的100x100矩形内容矩形)。

因此最终矩形的x坐标变为: center.x / currentScale - (scrollView.frame.size.width / 2)+ scrollView.contentOffset.x / currentScale = 75 / .5 - 100/2 + 100 / .5 = 150 - 50 + 200 = 300。

在这种情况下,作为正方形,y坐标的计算是相同的。 我们确实放大了右下角的100x100矩形,在较大的400x400内容视图中,它的起源为300,300。

所以这里是你如何计算缩放矩形的大小和来源:     zoomRect.size.height = mScrollView.frame.size.height / scale;     zoomRect.size.width = mScrollView.frame.size.width / scale;

zoomRect.origin.x = center.x/currentScale - (mScrollView.frame.size.width/2) + mScrollView.contentOffset.x/currentScale;
zoomRect.origin.y = center.y/currentScale - (mScrollView.frame.size.height/2) + mScrollView.contentOffset.y/currentScale;

希望这是有道理的;如果不勾勒出各种正方形/矩形,很难用书面解释。

干杯, Raf Colasante