Получение видимого прямоугольника содержимого UIScrollView - PullRequest
69 голосов
/ 15 мая 2009

Как я могу узнать прямоугольник (CGRect) содержимого отображаемого представления, которое фактически отображается на экране.

myScrollView.bounds

Приведенный выше код работает, когда нет масштабирования, но как только вы разрешаете масштабирование, он нарушается при масштабах, отличных от 1.

Чтобы уточнить, я хочу CGRect, который содержит видимую область содержимого представления прокрутки, относительно содержимого. (т. е. если это масштаб 2, то размер прямоугольника будет вдвое меньше размера представления прокрутки, если масштаб масштабирования 0,5 будет удвоен.)

Ответы [ 8 ]

106 голосов
/ 03 июля 2012

Или вы могли бы просто сделать

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

Swift

let visibleRect = scrollView.convert(scrollView.bounds, to: zoomedSubview)
82 голосов
/ 16 мая 2009

Отвечая на мой собственный вопрос, главным образом благодаря ответу Джима Дови, который не совсем помог, но дал мне основу для моего ответа:

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(), который нарушал бы код всякий раз, когда он больше.

28 голосов
/ 15 мая 2009

Вы должны вычислить его, используя свойства contentOffset и contentSize из UIScrollView, например:

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;
}

Помимо: я использую isless (), isgreater (), isequal () и т. Д. Из math.h, потому что они (предположительно) будут делать правильные вещи в отношении «неупорядоченных» результатов сравнения с плавающей точкой и других странных и замечательных архитектур конкретные случаи FP.


Редактировать: вам нужно использовать bounds.size вместо contentSize при расчете visibleRect.size.

10 голосов
/ 07 августа 2012

Укороченная версия:

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

Я не уверен, что это определенное поведение, но почти все подклассы UIView имеют источник bounds, установленный в (0,0) UIScrollViews, однако, имеют источник, установленный в contentOffset.

5 голосов
/ 12 декабря 2013

чуть более общее решение будет:

 [scrollView convertRect:scrollView.bounds
                             toView:[scrollView.delegate viewForZoomingInScrollView:scrollView]];
2 голосов
/ 30 января 2012
CGRect visibleRect;
visibleRect.origin = scrollView.contentOffset;
visibleRect.size = scrollView.frame.size;
0 голосов
/ 23 февраля 2019

Swift 4.0:

Мой ответ адаптируется Ответ Тренскова на Swift 4.0:

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

, где scrollView - это вид свитка, а subView - вид внутри scrollView, который можно масштабировать и который содержит все содержимое внутри свитка.

0 голосов
/ 15 мая 2009

Я не думаю, что UIScrollView дает вам этот прямоугольник напрямую, но я думаю, что у вас есть все необходимые элементы для его вычисления.

Комбинация границ, contentOffset и zoomScale должна быть всем, что вам нужно для создания прямоугольника, который вы ищете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...