【问题标题】:Getting the visible rect of an UIScrollView's content获取 UIScrollView 内容的可见矩形
【发布时间】:2010-10-26 11:31:17
【问题描述】:

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

myScrollView.bounds

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

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

【问题讨论】:

  • 你的问题本身已经解决了我的问题。我正在寻找滚动视图的可见矩形!为你 +1。

标签: objective-c iphone uiscrollview


【解决方案1】:

或者你可以这样做

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

斯威夫特

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

【讨论】:

  • zoomedSubview 是您不希望获得可见矩形的子视图。
  • zoomedSubview 是在“scrollView”中放大/缩小或滚动的 UIView。它与您从 UIScrollViewDelegate 的 (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView 方法的实现返回的 UIView 相同。
【解决方案2】:

回答我自己的问题,主要感谢 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。还稍微简化了数学,并没有完全看到 isless() 的用途,它会在代码更大时破坏代码。

【讨论】:

  • 这似乎在 iOS 3.2+ 和 CATiledLayer 上失败 - 无论如何,scrollView 的 zoomScale 始终设置为(例如在 iPad 上:)“2.0”。我知道 UIScrollView 在 iOS 3.2 中发生了变化——也许它破坏了这个解决方法?还是 CATiledLayer 破坏了它?叹息
  • 更新:这确实适用于 iOS 4+ - 除非您忘记实现 UIScrollViewDelegate 方法“scrollViewDidEndZooming:withView:atScale:”。注意:方法可以为空!但这是一个 Apple 实现错误,如果该方法不存在...... Apple 无法更新自己的 zoomScale 属性(谁知道还有哪些其他错误?)
  • @kenneth Ballenegger 代码中的“比例”(float theScale = 1.0 / scale;)是什么?
  • 其实,Trenskow 下面的回答要好得多。让系统为您完成。
【解决方案3】:

您必须使用 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 案例。


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

【讨论】:

  • 我认为 visibleRect.size = scrollView.frame.size;不是 contentSize ))
  • @property(nonatomic) CGSize contentSize; // 默认 CGSizeZero
【解决方案4】:

短版:

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

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

【讨论】:

    【解决方案5】:

    更通用的解决方案是:

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

    【讨论】:

      【解决方案6】:
      CGRect visibleRect;
      visibleRect.origin = scrollView.contentOffset;
      visibleRect.size = scrollView.frame.size;
      

      【讨论】:

        【解决方案7】:

        Swift 4.0:

        我的回答使 Trenskow's answer 适应 Swift 4.0:

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

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

        【讨论】:

          【解决方案8】:

          我不认为 UIScrollView 直接给你那个矩形,但我认为你有所有必要的项目来计算它。

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

          【讨论】:

            猜你喜欢
            • 2011-05-21
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-10-10
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多