Похоже, это лучший ресурс для этого вопроса в интернете. Другое близкое решение можно найти здесь .
Я решил эту проблему весьма удовлетворительным образом, по сути, заменив свой собственный распознаватель жестов в уравнении. Я настоятельно рекомендую всем, кто пытается добиться эффекта, запрошенного оригинальным постером, рассмотреть эту альтернативу вместо агрессивного подкласса UIScrollView
.
Следующий процесс обеспечит:
A UIScrollView
с вашим пользовательским представлением
Увеличение и панорамирование двумя пальцами (через UIPinchGestureRecognizer
)
Обработка событий вашего просмотра для всех остальных касаний
Во-первых, давайте предположим, что у вас есть контроллер вида и его вид. В IB сделайте представление подпредставлением scrollView и отрегулируйте правила изменения размера вашего представления так, чтобы оно не менялось. В атрибутах прокрутки включите все, что говорит "отказов" и выключите off"delaysContentTouches
". Кроме того, для масштабирования min и max необходимо установить значение, отличное от значения по умолчанию, равного 1,0, поскольку, как утверждают документы Apple, это необходимо для увеличения.
Создайте пользовательский подкласс UIScrollView
, и сделайте этот scrollview этим пользовательским подклассом. Добавьте выход к вашему контроллеру представления для scrollview и подключите их. Теперь вы полностью настроены.
Вам потребуется добавить следующий код в подкласс UIScrollView
, чтобы он прозрачно пропускал события касания (я подозреваю, что это можно сделать более элегантно, возможно, даже обходя подкласс в целом):
#pragma mark -
#pragma mark Event Passing
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[self.nextResponder touchesBegan:touches withEvent:event];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
[self.nextResponder touchesMoved:touches withEvent:event];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[self.nextResponder touchesEnded:touches withEvent:event];
}
- (BOOL)touchesShouldCancelInContentView:(UIView *)view {
return NO;
}
Добавьте этот код к вашему контроллеру представления:
- (void)setupGestures {
UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinchGesture:)];
[self.view addGestureRecognizer:pinchGesture];
[pinchGesture release];
}
- (IBAction)handlePinchGesture:(UIPinchGestureRecognizer *)sender {
if ( sender.state == UIGestureRecognizerStateBegan ) {
//Hold values
previousLocation = [sender locationInView:self.view];
previousOffset = self.scrollView.contentOffset;
previousScale = self.scrollView.zoomScale;
} else if ( sender.state == UIGestureRecognizerStateChanged ) {
//Zoom
[self.scrollView setZoomScale:previousScale*sender.scale animated:NO];
//Move
location = [sender locationInView:self.view];
CGPoint offset = CGPointMake(previousOffset.x+(previousLocation.x-location.x), previousOffset.y+(previousLocation.y-location.y));
[self.scrollView setContentOffset:offset animated:NO];
} else {
if ( previousScale*sender.scale < 1.15 && previousScale*sender.scale > .85 )
[self.scrollView setZoomScale:1.0 animated:YES];
}
}
Обратите внимание, что в этом методе есть ссылки на ряд свойств, которые вы должны определить в файлах классов вашего контроллера представления:
CGFloat previousScale;
CGPoint previousOffset;
CGPoint previousLocation;
CGPoint location;
Хорошо, вот и все!
К сожалению, я не смог заставить scrollView показывать свои скроллеры во время жеста. Я перепробовал все эти стратегии:
//Scroll indicators
self.scrollView.showsVerticalScrollIndicator = YES;
self.scrollView.showsVerticalScrollIndicator = YES;
[self.scrollView flashScrollIndicators];
[self.scrollView setNeedsDisplay];
Одна вещь, которая мне действительно понравилась, это то, что если вы посмотрите на последнюю строку, то заметите, что она захватывает любое окончательное масштабирование, которое составляет около 100%, и просто округляет его до этого. Вы можете настроить свой уровень терпимости; Я видел это в режиме масштабирования Страниц и думал, что это будет приятное прикосновение.