UIScrollView zoomToRect не масштабируется до заданного прямоугольника (создан из UITouch CGPoint) - PullRequest
6 голосов
/ 05 марта 2010

Мое приложение имеет UIScrollView с одним подпредставлением. Подвид - это расширенный UIView, который печатает страницу PDF для себя, используя слои в событии drawLayer.

Масштабирование с использованием встроенного сжатия прекрасно работает. setZoomScale также работает как положено.

Я боролся с функцией zoomToRect. Я нашел онлайн пример, который делает переменную zoomRect CGRect из данного CGPoint.

В функции touchesEnded, если было двойное касание, и они были полностью уменьшены, я хочу увеличить изображение PDFUIView, который я создал, как если бы они были в центре пальца, где они дважды касались.

Итак, предположим, что я передаю переменную UITouch своей функции, которая использует zoomToRect, если они дважды касаются.

Я начал со следующей функции, которую нашел на сайте яблок:

http://developer.apple.com/iphone/library/documentation/WindowsViews/Conceptual/UIScrollView_pg/ZoomZoom/ZoomZoom.html

Ниже приведена модифицированная версия для моего расширенного класса UIScrollView:

- (void)zoomToCenter:(float)scale withCenter:(CGPoint)center {     

    CGRect zoomRect;
    zoomRect.size.height = self.frame.size.height / scale;
    zoomRect.size.width  = self.frame.size.width  / scale;

    zoomRect.origin.x = center.x - (zoomRect.size.width  / 2.0);
    zoomRect.origin.y = center.y - (zoomRect.size.height / 2.0); 

    //return zoomRect;

    [self zoomToRect:zoomRect animated:YES];

} 

Когда я делаю это, кажется, что UIScrollView масштабируется с использованием нижнего правого края zoomRect выше, а не центра.

Если я сделаю UIView таким, как этот

UIView *v = [[UIView alloc] initWithFrame:zoomRect]; 
[v setBackgroundColor:[UIView redColor]];
[self addSubview:v];

Красная коробка отображается с мертвой точкой касания в центре.

Обратите внимание: я пишу это с моего ПК, я вспоминаю, как возился с разделенной на две части на моем Mac, поэтому просто предположим, что это рисует прямоугольник с точкой касания в центре. Если бы UIView отклонился от центра, но увеличил масштаб до нужного места, все было бы хорошо.

Однако, что происходит, когда он преобразует zoomToRect, кажется, что он использует нижний правый угол от zoomRect в верхнем левом углу увеличенных результатов.

Кроме того, я заметил, что в зависимости от того, где я щелкаю UIScrollView, он привязывается к разным точкам. Похоже, что крест посередине посередине и как-то отражает точки, как будто где-то слева от середины - отрицательное отражение, а где-нибудь справа от середины - положительное отражение?

Это кажется сложным, разве не нужно просто увеличить масштаб прямоугольника, который был нарисован, когда UIView смог нарисовать?

Я использовал много исследований, чтобы выяснить, как создать PDF, который масштабируется с высоким качеством, поэтому я предполагаю, что использование CALayer может привести к отказу от системы координат? Но для UIScrollView он должен просто рассматривать его как представление с размерами 768x985.

Это что-то сложное, пожалуйста, предположите, что код для создания zoomRect все в порядке. Что-то более глубокое с CALayer в UIView, которое есть в UIScrollView ....

Ответы [ 8 ]

5 голосов
/ 09 марта 2011

Хорошо, еще один ответ:

Подпрограмма Apple работает для меня, но вам нужно, чтобы распознаватель жестов преобразовывал точку касания в координаты imageView, а не в скроллер.

Пример Apple делает это, но так как наше приложение работает по-другому (мы меняем UIImageView), поэтому gestRecongnizer был настроен в uiscrollview - который отлично работает, но вы должны сделать это в handleDoubleTap:

Это свободно основано на примере кода Apple "TaptoZoom", но, как я уже сказал, нам нужен наш распознаватель жестов, подключенный к представлению прокрутки.

- (void)handleDoubleTap:(UIGestureRecognizer *)gestureRecognizer {
    // double tap zooms in
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(handleSingleTap:) object:nil];
    float newScale = [imageScrollView zoomScale] * 1.5;
    // Note we need to get location of the tap in the imageView coords, not the imageScrollView
    CGRect zoomRect = [self zoomRectForScale:newScale withCenter:[gestureRecognizer locationInView:imageView]];
    [imageScrollView zoomToRect:zoomRect animated:YES];
}
4 голосов
/ 12 июня 2013
   Declare BOOL isZoom; in .h


     -(void)handleDoubleTap:(UIGestureRecognizer *)recognizer {  
            if(isZoom){
                CGPoint Pointview=[recognizer locationInView:self];
                CGFloat newZoomscal=3.0;

                newZoomscal=MIN(newZoomscal, self.maximumZoomScale);

                CGSize scrollViewSize=self.bounds.size;

                CGFloat w=scrollViewSize.width/newZoomscal;
                CGFloat h=scrollViewSize.height /newZoomscal;
                CGFloat x= Pointview.x-(w/2.0);
                CGFloat y = Pointview.y-(h/2.0);

                CGRect rectTozoom=CGRectMake(x, y, w, h);
                [self zoomToRect:rectTozoom animated:YES]; 

                [self setZoomScale:3.0 animated:YES]; 
                isZoom=NO;
            }
            else{ 
                [self setZoomScale:1.0 animated:YES]; 
                isZoom=YES;
            }
        } 
1 голос
/ 16 февраля 2011

В моем случае это было:

zoomRect.origin.x    = center.x / self.zoomScale - (zoomRect.size.width  / 2.0);
zoomRect.origin.y    = center.y / self.zoomScale  - (zoomRect.size.height / 2.0);
1 голос
/ 23 ноября 2010

Я заметил, что используемое вами яблоко не масштабируется должным образом, если изображение начинается с zoomScale меньше 1, потому что источник zoomRect неверен. Я отредактировал это, чтобы работать правильно. Вот код:

- (CGRect)zoomRectForScale:(float)scale withCenter:(CGPoint)center {

CGRect zoomRect;

// the zoom rect is in the content view's coordinates. 
//    At a zoom scale of 1.0, it would be the size of the imageScrollView's bounds.
//    As the zoom scale decreases, so more content is visible, the size of the rect grows.
zoomRect.size.height = [self frame].size.height / scale;
zoomRect.size.width  = [self frame].size.width / scale;


// choose an origin so as to get the right center.
zoomRect.origin.x = (center.x * (2 - self.minimumZoomScale) - (zoomRect.size.width  / 2.0));
zoomRect.origin.y = (center.y * (2 - self.minimumZoomScale) - (zoomRect.size.height / 2.0));

return zoomRect;
}

Ключом является эта часть, умножающая центральное значение на (2 - self.minimumZoomScale). Надеюсь, это поможет.

0 голосов
/ 14 октября 2011

Я не согласен с одним из вышеприведенных комментариев о том, что вам никогда не следует умножать координаты центра на какой-то фактор.

Скажем, что в настоящее время вы отображаете полное изображение 400x400px или файл PDF в виде прокрутки 100x100 и хотитеразрешить пользователям удваивать размер контента до 1: 1.Если дважды щелкнуть мышью в точке (75,75), вы ожидаете, что увеличенный прямоугольник будет иметь источник 100,100 и размер 100x100 в новом представлении содержимого 200x200.Таким образом, исходная точка касания (75,75) теперь (150,150) в новом пространстве 200x200.

Теперь, после завершения действия масштабирования # 1, если вы снова дважды нажмете на (75,75) внутриНовый прямоугольник 100x100 (который является нижним правым квадратом большего прямоугольника 200x200), вы ожидаете, что пользователю будет показан нижний правый квадрат 100x100 большего изображения, которое теперь будет увеличено до 400x400 пикселей.

Чтобы вычислить происхождение этого последнего прямоугольника 100x100 в большем прямоугольнике 400x400, вам необходимо учитывать масштаб и текущее смещение содержимого (поскольку перед этим последним действием масштабирования мы отображали нижний правый прямоугольник 100x100 в прямоугольнике содержимого 200x200).).

Таким образом, координата x конечного прямоугольника становится: center.x / currentScale - (scrollView.frame.size.width / 2) + scrollView.contentOffset.x / currentScale = 75 / .5 - 100/2+ 100 / .5 = 150 - 50 + 200 = 300.

В этом случае, будучи квадратом, вычисление для координаты y такое же.И мы действительно увеличили нижний правый прямоугольник 100x100, который в увеличенном представлении содержимого 400x400 имеет исходное значение 300 300.

Итак, вот как можно рассчитать размер и происхождение прямоугольника масштабирования: zoomRect.size.height= mScrollView.frame.size.height / scale;zoomRect.size.width = mScrollView.frame.size.width / scale;

zoomRect.origin.x = center.x/currentScale - (mScrollView.frame.size.width/2) + mScrollView.contentOffset.x/currentScale;
zoomRect.origin.y = center.y/currentScale - (mScrollView.frame.size.height/2) + mScrollView.contentOffset.y/currentScale;

Надеюсь, это имело смысл;трудно объяснить это в письменном виде, не набрасывая различные квадраты / прямоугольники.

Приветствия, Раф Коласанте

0 голосов
/ 01 апреля 2011

Я пробовал разные решения, но это выглядит лучшим разрешением Это действительно прямо и концептуально?

CGRect frame = [[UIScreen mainScreen] applicationFrame];
scrollView.contentInset = UIEdgeInsetsMake(frame.size.height/2,
                 frame.size.width/2,
                 frame.size.height/2,
                 frame.size.width/2); 
0 голосов
/ 24 августа 2010

У меня такое же поведение, и это очень расстраивает ... Прямоугольник, который подается в UIScrollView, идеален ... но, на мой взгляд, независимо от того, что я делаю, что связано с изменением zoomScale программно, всегда масштабирует и масштабирует до координаты 0,0, несмотря ни на что.

Я пытался просто изменить zoomScale, я пробовал zoomToRect, я пробовал их все, и каждую минуту, когда я касаюсь zoomScale в коде, он идет с координатой 0,0.

Мне также пришлось добавить и явно указать setContentSize к измененному изображению в просмотре прокрутки после операции масштабирования, иначе я не могу прокрутить после увеличения или уменьшения.

Это ошибка в 3.1.3 или как?

0 голосов
/ 30 апреля 2010

У меня было что-то похожее, и это потому, что я не настраивал значения center.x и center.y, а также делил их на шкалу (используя center.x / scale и center.y / scale). Может быть, я не правильно читаю ваш код.

...