UIGestureRecognizer на UIImageView


179

У мене є UIImageView, який я хочу мати можливість змінити розмір і повернути і т.д.

Чи UIGestureRecognizerможна додати до UIImageView?

Я хотів би додати розпізнавач rotate and pinch до 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_GestureRecognizers про те, як зробити масштаб / поворот.

77
+1 сидів тут протягом століть, намагаючись зрозуміти, чому мої жести не працюватимуть. "Перевірте, чи ввімкнено" UserInteractionEnabled "ТАК на UIImageView." Дякую!
Critter

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

6
imageView.userInteractionEnabled = ТАК; це ключ! Дякую.
HamasN

3
userInteractionEnabledусе ще має бути встановлено YES / true у 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і a UIPanGestureRecognizer.

Спочатку в 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

Швидкий 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.) У свій поглядDidLoad додайте наступний код:

// 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-programatic
Dan Beaulieu

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

Для любителів блоків ви можете використовувати 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.