我怎样才能找出在屏幕上实际可见的显示视图的正确内容(CGRect)。
myScrollView.bounds
上面的代码在没有缩放的情况下可以工作,但是一旦允许缩放,它就会在1以外的缩放比例上出现故障。
为了澄清,我需要一个 CGRect,它包含滚动视图内容相对于内容的可见区域。(即。如果是缩放比例为2,则最近的尺寸将是滚动视图尺寸的一半,如果是缩放比例为0.5,则为两倍。)
我不认为 UIScrollView 可以直接给出那个矩形,但是我认为您拥有计算矩形所需的所有条目。
边界、 contentOffset 和 zoomScale 的组合应该是创建所需矩形的全部内容。
您必须使用 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 () ,isbetter () ,isequal ()等,因为(大概)这些对于“无序的”浮点比较结果和其他奇怪而精彩的特定于架构的 FP 案例来说是正确的。
编辑: 在计算 visibleRect.size时,需要使用 bounds.size而不是 contentSize。
visibleRect.size
bounds.size
contentSize
回答我自己的问题,主要是因为吉姆•多维(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;
主要的区别在于 visableRect 的大小应该是 scrollView.bounds.size,而不是 scrollView.contentSize,后者是内容视图的大小。也简化了数学一点,并没有完全看到使用 isless(),这将破坏代码每当它更大。
scrollView.bounds.size
scrollView.contentSize
isless()
CGRect visibleRect; visibleRect.origin = scrollView.contentOffset; visibleRect.size = scrollView.frame.size;
或者你可以直接
CGRect visibleRect = [scrollView convertRect:scrollView.bounds toView:zoomedSubview];
斯威夫特
let visibleRect = scrollView.convert(scrollView.bounds, to: zoomedSubview)
简短版:
CGRect visibleRect = CGRectApplyAffineTransform(scrollView.bounds, CGAffineTransformMakeScale(1.0 / scrollView.zoomScale, 1.0 / scrollView.zoomScale));
我不确定这是否是已定义的行为,但几乎所有 UIView 子类的 bounds原点都设置为(0,0)。但是,UIScrollView 的原点设置为 contentOffset。
bounds
contentOffset
一个更普遍的解决办法是:
[scrollView convertRect:scrollView.bounds toView:[scrollView.delegate viewForZoomingInScrollView:scrollView]];
Swift 4.0:
我的回答将 Trenskow 的回答改编成了 Swift 4.0:
let visible = scrollView.convert(scrollView.bounds, to: subView)
其中 scrollView是卷轴的视图,而 subView是 scrollView内部的视图,它是可缩放的,包含卷轴内部的所有内容。
scrollView
subView