Я предлагаю вам другой подход. Не создавайте постоянно новые изображения для добавления в UIImageView
. Вместо этого настройте иерархию представления следующим образом:
White view
"Hole" view (just a regular UIView)
Image view
То есть белый вид имеет вид отверстия в качестве подпредставления. Вид с отверстием имеет UIImageView
в качестве подпредставления.
Для вида отверстия должно быть установлено свойство clipsToBounds
, установленное в YES (вы можете установить его с помощью кода или в своем кончике).
Размер изображения должен иметь размер, равный размеру его изображения. Это, конечно, будет больше, чем размер отверстия.
И это очень и очень важно: центр вида изображения должен быть установлен в центр вида отверстия.
Вот код, который я использовал в своем тестовом проекте для настройки. Белый вид self.view
. Я начинаю с отверстия, центрированного на белом виде, и устанавливаю центр вида изображения в центр вида с отверстием.
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:YES];
CGRect bounds = self.view.bounds;
self.holeView.center = CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds));
self.holeView.clipsToBounds = YES;
bounds = self.holeView.bounds;
self.imageView.center = CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds));
self.imageView.bounds = (CGRect){ CGPointZero, self.imageView.image.size };
}
Я также установил размер изображения в соответствии с размером его изображения. Возможно, вы захотите установить размер белого вида.
Для панорамирования и поворота отверстия я собираюсь установить holeView.transform
. Я не собираюсь менять holeView.frame
или holeView.center
. У меня есть две переменные экземпляра, _holeOffset
и _holeRotation
, которые я использую для вычисления преобразования. Хитрость в том, чтобы сделать его похожим на дыру в белом виде, открывая вид изображения, - применить преобразование обратное к виду изображения, отменив эффекты преобразования вида дыр:
- (void)updateTransforms {
CGAffineTransform holeTransform = CGAffineTransformIdentity;
holeTransform = CGAffineTransformTranslate(holeTransform, _holeOffset.x, _holeOffset.y);
holeTransform = CGAffineTransformRotate(holeTransform, _holeRotation);
self.holeView.transform = holeTransform;
self.imageView.transform = CGAffineTransformInvert(holeTransform);
}
Эта уловка использования обратного преобразования в подпредставлении работает, только если центр подпредставления находится в центре его суперпредставления. (Технически точки привязки должны быть выровнены, но по умолчанию точка привязки вида является его центром.)
Я поставил UIPanGestureRecognizer
на holeView
. Я настроил его для отправки panGesture:
на мой контроллер вида:
- (IBAction)panGesture:(UIPanGestureRecognizer *)sender {
CGPoint offset = [sender translationInView:self.view];
[sender setTranslation:CGPointZero inView:self.view];
_holeOffset.x += offset.x;
_holeOffset.y += offset.y;
[self updateTransforms];
}
Я также поставил UIRotationGestureRecognizer
на holeView
. Я настроил его для отправки rotationGesture:
на мой контроллер вида:
- (IBAction)rotationGesture:(UIRotationGestureRecognizer *)sender {
_holeRotation += sender.rotation;
sender.rotation = 0;
[self updateTransforms];
}