objective-c 获取 UIScrollView 内容的可见矩形

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/868288/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 21:33:16  来源:igfitidea点击:

Getting the visible rect of an UIScrollView's content

objective-ciphoneuiscrollview

提问by Kenneth Ballenegger

How can I go about finding out the rect (CGRect) of the content of a displayed view that is actually visible on screen.

我怎样才能找出屏幕上实际可见的显示视图的内容的矩形(CGRect)。

myScrollView.bounds

The code above works when there's no zooming, but as soon as you allow zooming, it breaks at zoom scales other than 1.

上面的代码在没有缩放时有效,但是一旦您允许缩放,它就会在 1 以外的缩放比例下中断。

To clarify, I want a CGRect that contains the visible area of the scroll view's content, relative to the content. (ie. if it's a zoom scale 2, the rect's size will be half of the scroll view's size, if it's at zoom scale 0.5, it'll be double.)

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

回答by Trenskow

Or you could simply do

或者你可以简单地做

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


Swift

迅速

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

回答by Kenneth Ballenegger

Answering my own question, mostly thanks to Jim Dovey's answer, which didn't quite do the trick, but gave me the base for my answer:

回答我自己的问题,主要归功于 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;

The main difference is that the size of the visibleRect ought to be scrollView.bounds.size, rather than scrollView.contentSizewhich is the size of the content view. Also simplified the math a bit, and didn't quite see the use for the isless()which would break the code whenever it's greater.

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

回答by Jim Dovey

You have to compute it using UIScrollView's contentOffset and contentSize properties, like so:

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

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

You can then log it for sanity-testing:

然后,您可以记录它以进行健全性测试:

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

To account for zooming (if this isn't already done by the contentSize property) you would need to divide each coordinate by the zoomScale, or for better performance you would multiply by 1.0 / zoomScale:

要考虑缩放(如果这不是由 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;
}

Aside: I use isless(), isgreater(), isequal() etc. from math.h because these will (presumably) do the right thing regarding 'unordered' floating-point comparison results and other weird & wonderful architecture-specific FP cases.

旁白:我使用 math.h 中的 isless()、isgreater()、isequal() 等,因为这些将(大概)对“无序”浮点比较结果和其他奇怪而精彩的特定于架构的 FP 案例做正确的事情.



Edit: You need to use bounds.sizeinstead of contentSizewhen calculating visibleRect.size.

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

回答by Frank Schmitt

Shorter version:

较短的版本:

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

I'm not sure if this is defined behavior, but almost all UIView subclasses have the origin of their boundsset to (0,0). UIScrollViews, however, have the origin set to contentOffset.

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

回答by Nikolay Shubenkov

a little more general solution would be:

一个更通用的解决方案是:

 [scrollView convertRect:scrollView.bounds
                             toView:[scrollView.delegate viewForZoomingInScrollView:scrollView]];

回答by Bas Dirkse

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

回答by Jonathan Arbogast

I don't think that a UIScrollView gives you that rectangle directly, but I think you have all the necessary items to calculate it.

我不认为 UIScrollView 直接为您提供该矩形,但我认为您拥有计算它的所有必要项。

A combination of the bounds, the contentOffset and the zoomScale should be all you need to create the rectangle you are looking for.

边界、contentOffset 和 zoomScale 的组合应该是创建您正在寻找的矩形所需的全部。

回答by RoberRM

Swift 4.0:

斯威夫特 4.0:

My answer adapts Trenskow's answerto Swift 4.0:

我的回答改编了Trenskow对 Swift 4.0的回答

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

where scrollViewis the view of the scroll, and subViewis the view inside scrollViewwhich is zoomable and contains all the contents inside the scroll.

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