获取UIScrollView内容的可见区域


71

如何找到屏幕上实际可见的显示视图的内容的矩形(CGRect)。

myScrollView.bounds

上面的代码在没有缩放时起作用,但是一旦允许缩放,它就会以非1的缩放比例中断。

为了澄清,我想要一个CGRect,其中包含滚动视图内容相对于内容的可见区域。(即,如果缩放比例为2,则矩形的大小将为滚动视图大小的一半,如果缩放比例为0.5,则其大小将为两倍。)


5
您的问题本身解决了我的问题。我在寻找scrollview的可见矩形!为您+1。
Bharat Dodeja,

Answers:


110

或者你可以简单地做

CGRect visibleRect = [scrollView convertRect:scrollView.bounds toView:zoomedSubview];

迅速

let visibleRect = scrollView.convert(scrollView.bounds, to: zoomedSubview)

2
zoomedSubview是您不希望获得可见矩形的子视图。
Trenskow

3
zoomedSubview是正在放大/缩小或在“ scrollView”中滚动的UIView。这是从UIScrollViewDelegate(UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView方法的实现中返回的UIView。
乌克兰亚历克斯

84

回答我自己的问题,在很大程度上要感谢吉姆·多维(Jim Dovey)的回答,虽然不能完全解决问题,但却为我提供了答案的基础:

CGRect visibleRect;
visibleRect.origin = scrollView.contentOffset;
visibleRect.size = scrollView.bounds.size;

float theScale = 1.0 / scale;
visibleRect.origin.x *= theScale;
visibleRect.origin.y *= theScale;
visibleRect.size.width *= theScale;
visibleRect.size.height *= theScale;

主要区别在于visibleRect的大小应为scrollView.bounds.size,而不是scrollView.contentSize内容视图的大小。还简化了数学运算,并没有完全看到for的用法,isless()只要代码更大,它将破坏代码。


在iOS 3.2及更高版本以及CATiledLayer的情况下,这似乎都失败了,无论如何,scrollView的zoomScale始终设置为(例如,在iPad上)“ 2.0”。我知道UIScrollView在iOS 3.2中已更改-也许它打破了此解决方法?还是CATiledLayer破坏了它?感叹
Adam

更新:这确实适用于iOS 4+-除非您忘记实现UIScrollViewDelegate方法“ scrollViewDidEndZooming:withView:atScale:”。注意:方法可以为空!但是,这是一个Apple实现错误,如果该方法不存在,那么... Apple无法更新自己的zoomScale属性(谁知道其他错误?)
亚当

@kenneth Ballenegger在您的代码中什么是“比例”(float theScale = 1.0 / scale;)?
希塔斯,2013年

3
实际上,Trenskow在下面的回答要好得多。让系统为您完成。
n13

28

您必须使用UIScrollView的contentOffset和contentSize属性来计算它,如下所示:

CGRect visibleRect;
visibleRect.origin = scrollView.contentOffset;
visibleRect.size = scrollView.contentSize;

然后,您可以将其记录下来以进行健全性测试:

NSLog( @"Visible rect: %@", NSStringFromCGRect(visibleRect) );

为了解决缩放问题(如果contentSize属性尚未完成此操作),您需要将每个坐标除以zoomScale,或者为了获得更好的性能,请乘以1.0 / zoomScale:

CGFloat scale = (CGFloat) 1.0 / scrollView.zoomScale;
if ( isless(scale, 1.0) )      // you need to #include <math.h> for isless()
{
    visibleRect.origin.x *= scale;
    visibleRect.origin.y *= scale;
    visibleRect.size.width *= scale;
    visibleRect.size.height *= scale;
}

另外:我使用math.h中的isless(),isgreater(),isequal()等,因为这些(大概)将对“无序”浮点比较结果以及其他奇怪而美妙的特定于FP的情况做正确的事情。


编辑:计算时需要使用bounds.size而不是。contentSizevisibleRect.size


7
我认为visibleRect.size = scrollView.frame.size; 不是contentSize))
氧气

@property(nonatomic)CGSize contentSize; //默认CGSizeZero
吉姆·多维

10

较短的版本:

CGRect visibleRect = CGRectApplyAffineTransform(scrollView.bounds, CGAffineTransformMakeScale(1.0 / scrollView.zoomScale, 1.0 / scrollView.zoomScale));

我不确定这是否是定义的行为,但是几乎所有UIView子类的来源都bounds设置为(0,0)。但是,UIScrollViews的原点设置为contentOffset



3
CGRect visibleRect;
visibleRect.origin = scrollView.contentOffset;
visibleRect.size = scrollView.frame.size;


0

Swift 4.0:

我的回答使Trenskow的回答适应了Swift 4.0:

let visible = scrollView.convert(scrollView.bounds, to: subView)

其中scrollView是滚动subView视图scrollView,是内部视图,该视图是可缩放的并且包含滚动内部的所有内容。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.