获取UIScrollView内容的可见rect

Ken*_*ger 69 iphone objective-c uiscrollview

我怎样才能找到屏幕上实际可见的显示视图内容的rect(CGRect).

myScrollView.bounds
Run Code Online (Sandbox Code Playgroud)

上面的代码在没有缩放时有效,但只要你允许缩放,它就会以1以外的缩放比例中断.

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

Tre*_*kow 106

或者你可以干脆做

CGRect visibleRect = [scrollView convertRect:scrollView.bounds toView:zoomedSubview];
Run Code Online (Sandbox Code Playgroud)

迅速

let visibleRect = scrollView.convert(scrollView.bounds, to: zoomedSubview)
Run Code Online (Sandbox Code Playgroud)

  • 什么是zoomedSubview? (8认同)
  • zoomedSubview是在"scrollView"中放大/缩小或滚动的UIView.您从UIScrollViewDelegate(UIView*)viewForZoomingInScrollView:(UIScrollView*)scrollView方法的实现返回的是相同的UIView. (3认同)
  • zoomedSubview是你想要获得可见矩形的子视图. (2认同)

Ken*_*ger 83

回答我自己的问题,主要归功于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;
Run Code Online (Sandbox Code Playgroud)

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

  • 实际上,下面的Trenskow答案要好得多.让系统为您完成. (3认同)

Jim*_*vey 28

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

CGRect visibleRect;
visibleRect.origin = scrollView.contentOffset;
visibleRect.size = scrollView.contentSize;
Run Code Online (Sandbox Code Playgroud)

然后,您可以将其记录以进行完整性测试:

NSLog( @"Visible rect: %@", NSStringFromCGRect(visibleRect) );
Run Code Online (Sandbox Code Playgroud)

考虑到缩放(如果这还没有由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;
}
Run Code Online (Sandbox Code Playgroud)

旁白:我使用math.h中的isless(),isgreater(),isequal()等因为这些(可能)对于"无序"浮点比较结果以及其他奇怪且精彩的架构特定FP案例做了正确的事情.


编辑:您需要使用bounds.size而不是contentSize计算时visibleRect.size.

  • 我认为visibleRect.size = scrollView.frame.size; 不是contentSize)) (7认同)

Fra*_*itt 10

更短的版本:

CGRect visibleRect = CGRectApplyAffineTransform(scrollView.bounds, CGAffineTransformMakeScale(1.0 / scrollView.zoomScale, 1.0 / scrollView.zoomScale));
Run Code Online (Sandbox Code Playgroud)

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


Nik*_*kov 5

更一般的解决方案是:

 [scrollView convertRect:scrollView.bounds
                             toView:[scrollView.delegate viewForZoomingInScrollView:scrollView]];
Run Code Online (Sandbox Code Playgroud)