Получение видимого прямоугольника содержимого UIScrollView

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

myScrollView.bounds

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

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

Ответ 1

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

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

Ответ 2

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

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

Ответ 3

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

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

Затем вы можете зарегистрировать его для проверки работоспособности:

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

Чтобы учесть масштабирование (если это еще не сделано с помощью свойства contentSize), вам нужно будет разделить каждую координату с помощью масштабирования, или для лучшей производительности вы будете умножать на 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.

Ответ 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

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

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