UIImageView上的UIGestureRecognizer


179

我有一个UIImageView,我希望能够调整大小和旋转等。

可以UIGestureRecognizer添加到UIImageView吗?

我想向UIImageView运行时创建的旋转添加捏识别器。

如何添加这些识别器?

Answers:


426

检查userInteractionEnabledYESUIImageView。然后,您可以添加一个手势识别器。

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在这里坐了很久,试图弄清楚为什么我的手势不起作用。“检查UIImageView上的userInteractionEnabled是否为YES。” 谢谢!
小动物

1
这肯定使我的工作比尝试对设置为整体视图的识别器设置限制要容易。谢谢!
乔什·科瓦奇

6
imageView.userInteractionEnabled = YES; 这是关键!谢谢。
HamasN

3
userInteractionEnabled在Xcode 8 Objective-C / Swift中仍然必须设置为YES / True
leanne

76

是的,可以将UIGestureRecognizer添加到UIImageView。如其他答案所述,记住将图片userInteractionEnabled属性设置为可以在图片视图上启用用户交互非常重要YES。UIImageView继承自UIView,后者的用户交互属性YES默认设置为,但是UIImageView的用户交互属性NO默认设置为。

UIImageView文档:

默认情况下,新的图像视图对象配置为忽略用户事件。如果要处理UIImageView的自定义子类中的事件,则必须在初始化对象后将userInteractionEnabled属性的值显式更改为YES。

无论如何,大部分的答案。这是一个如何UIImageView使用a UIPinchGestureRecognizer,a UIRotationGestureRecognizer和a 创建a的示例UIPanGestureRecognizer

首先,使用viewDidLoad或您选择的另一种方法,创建图像视图,为其提供图像,框架并启用其用户交互。然后按如下所示创建三个手势。确保使用其委托属性(最有可能设置为self)。要求同时使用多个手势。

- (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源代码。谢谢你
Alejandro Luengo 2014年

1
清除,一步一个脚印,真棒交代
艾尔文

1
谢谢您,这在一两个页面中确实做到了,Apple和其他人多年来没有完成几十个教程。我认为iOS中还可能存在许多其他可能的事情,但是由于混淆和误解,它们对我们失去了。
Zack Morris

好答案,最好的答案。非常感谢您的耐心配合。
Jorg B Jorge

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.)在您的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)
    }
}


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];
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.