UIGestureRecognizer на UIImageView


179

У меня есть UIImageView, который я хочу иметь возможность изменять размеры и вращаться и т. Д.

Можно UIGestureRecognizerли добавить к UIImageView?

Я хотел бы добавить повернуть и ущипнуть распознаватель, UIImageViewкоторый будет создан во время выполнения.

Как добавить эти распознаватели?

Ответы:


426

Убедитесь , что userInteractionEnabledэто YESна UIImageView. Затем вы можете добавить распознаватель жестов.

imageView.userInteractionEnabled = YES;
UIPinchGestureRecognizer *pgr = [[UIPinchGestureRecognizer alloc] 
    initWithTarget:self action:@selector(handlePinch:)];
pgr.delegate = self;
[imageView addGestureRecognizer:pgr];
[pgr release];
:
:
- (void)handlePinch:(UIPinchGestureRecognizer *)pinchGestureRecognizer
{
  //handle pinch...
}

5
Нет, это просто показывает, как добавить распознаватели жестов. Вы должны сделать реальное увеличение / вращение в обработчиках жестов. Посмотрите пример приложения Touches_GestureRecognizer о том, как сделать масштабирование / поворот.

77
+1 сидел здесь целую вечность, пытаясь выяснить, почему мои жесты не сработали ... "Проверьте, что userInteractionEnabled имеет значение YES в UIImageView." Спасибо!
Зверь

1
Это определенно сделало мою работу проще, чем пытаться установить ограничения для распознавателя, установленного для общего вида. Спасибо!
Джош Ковач

6
imageView.userInteractionEnabled = YES; это ключ! Спасибо.
HamasN

3
userInteractionEnabledвсе еще должен быть установлен в ДА / истина в Xcode 8 Objective-C / Swift
leanne

76

Да, UIGestureRecognizer может быть добавлен в UIImageView. Как указано в другом ответе, очень важно помнить, чтобы разрешить взаимодействие с пользователем в представлении изображения, установив его userInteractionEnabledсвойство равным YES. UIImageView наследует от UIView, чье свойство взаимодействия с пользователем установлено YESпо умолчанию, однако свойство взаимодействия с пользователем UIImageView установлено NOпо умолчанию.

Из документов UIImageView:

Новые объекты просмотра изображений по умолчанию настроены на игнорирование пользовательских событий. Если вы хотите обрабатывать события в пользовательском подклассе UIImageView, вы должны явно изменить значение свойства userInteractionEnabled на YES после инициализации объекта.

Во всяком случае, основная часть ответа. Вот пример того, как создать UIImageViewс a UIPinchGestureRecognizer, a UIRotationGestureRecognizerи aUIPanGestureRecognizer .

Во-первых, viewDidLoadили другим способом по вашему выбору создайте представление изображения, присвойте ему изображение, рамку и включите взаимодействие с пользователем. Затем создайте три жеста следующим образом. Обязательно используйте их делегатское свойство (скорее всего, для себя). Для этого потребуется использовать несколько жестов одновременно.

- (void)viewDidLoad
{
    [super viewDidLoad];

    // set up the image view
    UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"someImage"]];
    [imageView setBounds:CGRectMake(0.0, 0.0, 120.0, 120.0)];
    [imageView setCenter:self.view.center];
    [imageView setUserInteractionEnabled:YES]; // <--- This is very important

    // create and configure the pinch gesture
    UIPinchGestureRecognizer *pinchGestureRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinchGestureDetected:)];
    [pinchGestureRecognizer setDelegate:self];
    [imageView addGestureRecognizer:pinchGestureRecognizer];

    // create and configure the rotation gesture
    UIRotationGestureRecognizer *rotationGestureRecognizer = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(rotationGestureDetected:)];
    [rotationGestureRecognizer setDelegate:self];
    [imageView addGestureRecognizer:rotationGestureRecognizer];

    // creat and configure the pan gesture
    UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGestureDetected:)];
    [panGestureRecognizer setDelegate:self];
    [imageView addGestureRecognizer:panGestureRecognizer];


    [self.view addSubview:imageView]; // add the image view as a subview of the view controllers view
}

Вот три метода, которые будут вызываться при обнаружении жестов на вашем экране. Внутри них мы проверим текущее состояние жеста, и если оно находится в начальном или измененном состоянии, UIGestureRecognizerStateмы прочтем свойство масштаба / вращения / перевода жеста, применим эти данные к аффинному преобразованию, применим аффинное преобразование к изображению. просмотреть, а затем сбросить масштаб жестов / поворот / перевод.

- (void)pinchGestureDetected:(UIPinchGestureRecognizer *)recognizer
{
    UIGestureRecognizerState state = [recognizer state];

    if (state == UIGestureRecognizerStateBegan || state == UIGestureRecognizerStateChanged)
    {
        CGFloat scale = [recognizer scale];
        [recognizer.view setTransform:CGAffineTransformScale(recognizer.view.transform, scale, scale)];
        [recognizer setScale:1.0];
    }
}

- (void)rotationGestureDetected:(UIRotationGestureRecognizer *)recognizer
{
    UIGestureRecognizerState state = [recognizer state];

    if (state == UIGestureRecognizerStateBegan || state == UIGestureRecognizerStateChanged)
    {
        CGFloat rotation = [recognizer rotation];
        [recognizer.view setTransform:CGAffineTransformRotate(recognizer.view.transform, rotation)];
        [recognizer setRotation:0];
    }
}

- (void)panGestureDetected:(UIPanGestureRecognizer *)recognizer
{
    UIGestureRecognizerState state = [recognizer state];

    if (state == UIGestureRecognizerStateBegan || state == UIGestureRecognizerStateChanged)
    {
        CGPoint translation = [recognizer translationInView:recognizer.view];
        [recognizer.view setTransform:CGAffineTransformTranslate(recognizer.view.transform, translation.x, translation.y)];
        [recognizer setTranslation:CGPointZero inView:recognizer.view];
    }
}

Наконец, что очень важно, вам нужно использовать метод UIGestureRecognizerDelegate,gestureRecognizer: shouldRecognizeSimultaneouslyWithGestureRecognizer чтобы жесты работали одновременно. Если эти три жеста являются единственными тремя жестами, которым этот класс назначен в качестве их делегата, то вы можете просто вернуться, YESкак показано ниже. Однако, если у вас есть дополнительные жесты, которым этот класс назначен в качестве их делегата, вам может потребоваться добавить логику в этот метод, чтобы определить, какой это жест, прежде чем разрешить им всем работать вместе.

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    return YES;
}

Не забудьте убедиться, что ваш класс соответствует протоколу UIGestureRecognizerDelegate . Для этого убедитесь, что ваш интерфейс выглядит примерно так:

@interface MyClass : MySuperClass <UIGestureRecognizerDelegate>

Если вы предпочитаете поиграть с кодом в рабочем примере проекта, созданный мной пример проекта, содержащий этот код, можно найти здесь.


1
На данный момент это лучший ответ, который я когда-либо видел на stackoverflow.com, полный подробный, хорошо прокомментированный и даже включающий исходный код на git. Спасибо за это
Алехандро Луенго

1
Ясно, шаг за шагом, потрясающее объяснение
Элвин

1
Спасибо, что сделали на одной или двух страницах то, что не удалось сделать нескольким дюжинам учебников за годы Apple и других. Я чувствую, что в iOS должно быть много других вещей, которые возможны, но из-за запутывания и непонимания они потеряны для нас.
Зак Моррис

Отличный ответ, лучший. Большое спасибо за ваше терпение.
Йорг Б Хорхе

13

Swift 4.2

myImageView.isUserInteractionEnabled = true
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(imageTapped))
tapGestureRecognizer.numberOfTapsRequired = 1
myImageView.addGestureRecognizer(tapGestureRecognizer)

и когда постучал:

@objc func imageTapped(_ sender: UITapGestureRecognizer) {
   // do something when image tapped
   print("image tapped")
}

11

Решение Swift 2.0

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

4 шага

1.) Унаследовать от UIGestureRecognizerDelegate, добавив его в подпись вашего класса.

class ViewController: UIViewController, UIGestureRecognizerDelegate {...}

2.) Управление перетаскиванием с вашего изображения в viewController для создания IBOutlet:

@IBOutlet weak var tapView: UIImageView!

3.) В ваш viewDidLoad добавьте следующий код:

// create an instance of UITapGestureRecognizer and tell it to run 
// an action we'll call "handleTap:"
let tap = UITapGestureRecognizer(target: self, action: Selector("handleTap:"))
// we use our delegate
tap.delegate = self
// allow for user interaction
tapView.userInteractionEnabled = true
// add tap as a gestureRecognizer to tapView
tapView.addGestureRecognizer(tap)

4.) Создайте функцию, которая будет вызываться при нажатии на распознаватель жестов. (Вы можете исключить, = nilесли вы выберете).

func handleTap(sender: UITapGestureRecognizer? = nil) {
    // just creating an alert to prove our tap worked!
    let tapAlert = UIAlertController(title: "hmmm...", message: "this actually worked?", preferredStyle: UIAlertControllerStyle.Alert)
    tapAlert.addAction(UIAlertAction(title: "OK", style: .Destructive, handler: nil))
    self.presentViewController(tapAlert, animated: true, completion: nil)
}

Ваш окончательный код должен выглядеть примерно так:

class ViewController: UIViewController, UIGestureRecognizerDelegate {

    @IBOutlet weak var tapView: UIImageView!

    override func viewDidLoad() {
        super.viewDidLoad()

        let tap = UITapGestureRecognizer(target: self, action: Selector("handleTap:"))
        tap.delegate = self
        tapView.userInteractionEnabled = true
        tapView.addGestureRecognizer(tap)
    }

    func handleTap(sender: UITapGestureRecognizer? = nil) {
        let tapAlert = UIAlertController(title: "hmmm...", message: "this actually worked?", preferredStyle: UIAlertControllerStyle.Alert)
        tapAlert.addAction(UIAlertAction(title: "OK", style: .Destructive, handler: nil))
        self.presentViewController(tapAlert, animated: true, completion: nil)
    }
}

1
я написал блог об этом здесь: codebeaulieu.com/3/UIGestureRecognier-programatics
Дэн Болье,

6

Я только что сделал это с swift4, добавив 3 жеста вместе в одном представлении

  1. UIPinchGestureRecognizer : увеличение и уменьшение масштаба.
  2. UIRotationGestureRecognizer : повернуть представление.
  3. UIPanGestureRecognizer : перетаскивание вида.

Вот мой пример кода

class ViewController: UIViewController: UIGestureRecognizerDelegate{
      //your image view that outlet from storyboard or xibs file.
     @IBOutlet weak var imgView: UIImageView!
     // declare gesture recognizer
     var panRecognizer: UIPanGestureRecognizer?
     var pinchRecognizer: UIPinchGestureRecognizer?
     var rotateRecognizer: UIRotationGestureRecognizer?

     override func viewDidLoad() {
          super.viewDidLoad()
          // Create gesture with target self(viewcontroller) and handler function.  
          self.panRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.handlePan(recognizer:)))
          self.pinchRecognizer = UIPinchGestureRecognizer(target: self, action: #selector(self.handlePinch(recognizer:)))
          self.rotateRecognizer = UIRotationGestureRecognizer(target: self, action: #selector(self.handleRotate(recognizer:)))
          //delegate gesture with UIGestureRecognizerDelegate
          pinchRecognizer?.delegate = self
          rotateRecognizer?.delegate = self
          panRecognizer?.delegate = self
          // than add gesture to imgView
          self.imgView.addGestureRecognizer(panRecognizer!)
          self.imgView.addGestureRecognizer(pinchRecognizer!)
          self.imgView.addGestureRecognizer(rotateRecognizer!)
     }

     // handle UIPanGestureRecognizer 
     @objc func handlePan(recognizer: UIPanGestureRecognizer) {    
          let gview = recognizer.view
          if recognizer.state == .began || recognizer.state == .changed {
               let translation = recognizer.translation(in: gview?.superview)
               gview?.center = CGPoint(x: (gview?.center.x)! + translation.x, y: (gview?.center.y)! + translation.y)
               recognizer.setTranslation(CGPoint.zero, in: gview?.superview)
          }
     }

     // handle UIPinchGestureRecognizer 
     @objc func handlePinch(recognizer: UIPinchGestureRecognizer) {
          if recognizer.state == .began || recognizer.state == .changed {
               recognizer.view?.transform = (recognizer.view?.transform.scaledBy(x: recognizer.scale, y: recognizer.scale))!
               recognizer.scale = 1.0
         }
     }   

     // handle UIRotationGestureRecognizer 
     @objc func handleRotate(recognizer: UIRotationGestureRecognizer) {
          if recognizer.state == .began || recognizer.state == .changed {
               recognizer.view?.transform = (recognizer.view?.transform.rotated(by: recognizer.rotation))!
               recognizer.rotation = 0.0
           }
     }

     // mark sure you override this function to make gestures work together 
     func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
         return true
     }

}

Любой вопрос, просто введите комментарий. Спасибо


3

SWIFT 3 Пример

override func viewDidLoad() {

    self.backgroundImageView.addGestureRecognizer(
        UITapGestureRecognizer.init(target: self, action:#selector(didTapImageview(_:)))
    )

    self.backgroundImageView.isUserInteractionEnabled = true
}

func didTapImageview(_ sender: Any) {
    // do something
}

Нет необходимости в делегатах-жестах или других реализациях, где это необходимо.


2

Вы также можете перетащить распознаватель жестов касанием к представлению изображения в Storyboard. Затем создайте действие по ctrl + dragкоду.


1

Для любителей Blocks вы можете использовать ALActionBlocks, чтобы добавить действие жестов в блоке

__weak ALViewController *wSelf = self;
imageView.userInteractionEnabled = YES;
UITapGestureRecognizer *gr = [[UITapGestureRecognizer alloc] initWithBlock:^(UITapGestureRecognizer *weakGR) {
    NSLog(@"pan %@", NSStringFromCGPoint([weakGR locationInView:wSelf.view]));
}];
[self.imageView addGestureRecognizer:gr];
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.