UIPinchGestureRecognizer和UIPanGestureRecognizer可以合并吗? [英] Can UIPinchGestureRecognizer and UIPanGestureRecognizer Be Merged?

查看:163
本文介绍了UIPinchGestureRecognizer和UIPanGestureRecognizer可以合并吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在努力弄清楚是否有可能创建一个组合UIPinchGestureRecognizer和UIPanGestureRecognizer的组合手势识别器。



我正在使用pan进行查看翻译和捏视图缩放。我正在进行增量矩阵连接,以导出应用于视图的结果最终变换矩阵。该矩阵具有缩放和平移。使用单独的手势识别器会导致抖动运动/缩放。不是我想要的。因此,我想在一个手势中处理一次缩放和翻译。有人可以说明如何做到这一点吗?

解决方案

6/14/14:更新了示例代码带有ARC的iOS 7+。



UIGestureRecognizers可以协同工作,您只需要确保不要删除当前视图的变换矩阵。使用CGAffineTransformScale方法和将变换作为输入的相关方法,而不是从头开始创建(除非您自己维护当前的旋转,缩放或平移。



下载Xcode项目





    1. 将它们添加到视图中并符合UIGestureRecognizerDelegate协议

        @interface ViewController()< UIGestureRecognizerDeleg ATE和GT; 

      @end

      @implementation ViewController

      - (void)viewDidLoad
      {
      [super viewDidLoad];

      UIView * blueView = [[UIView alloc] initWithFrame:CGRectMake(100,100,150,150)];
      blueView.backgroundColor = [UIColor blueColor];
      [self.view addSubview:blueView];
      [self addMovementGesturesToView:blueView];

      // UIImageView和UILabel默认没有userInteractionEnabled!
      UIImageView * imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@BombDodge.png]]; // Xcode项目中的任何图像
      imageView.center = CGPointMake(100,250);
      [imageView sizeToFit];
      [self.view addSubview:imageView];
      [self addMovementGesturesToView:imageView];

      //注意:更改字体大小比缩放字体更清晰!
      UILabel * label = [[UILabel alloc] init];
      label.text = @Hello Gestures!;
      label.font = [UIFont systemFontOfSize:30];
      label.textColor = [UIColor blackColor];
      [label sizeToFit];
      label.center = CGPointMake(100,400);
      [self.view addSubview:label];
      [self addMovementGesturesToView:label];
      }

      - (void)addMovementGesturesToView:(UIView *)view {
      view.userInteractionEnabled = YES; //启用用户交互

      UIPanGestureRecognizer * panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGesture :)];
      panGesture.delegate = self;
      [查看addGestureRecognizer:panGesture];

      UIPinchGestureRecognizer * pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinchGesture :)];
      pinchGesture.delegate = self;
      [查看addGestureRecognizer:pinchGesture];
      }


    2. 实施手势方法

         - (void)handlePanGesture:(UIPanGestureRecognizer *)panGesture {
      CGPoint translation = [panGesture translationInView:panGesture.view.superview];

      if(UIGestureRecognizerStateBegan == panGesture.state || UIGestureRecognizerStateChanged == panGesture.state){
      panGesture.view.center = CGPointMake(panGesture.view.center.x + translation.x,
      panGesture.view.center.y + translation.y);
      //重置翻译,这样我们就可以获得翻译delta(即翻译的变化)
      [panGesture setTranslation:CGPointZero inView:self.view];
      }
      //结束/失败/取消状态不需要任何逻辑
      }

      - (void)handlePinchGesture:(UIPinchGestureRecognizer *)pinchGesture {

      if(UIGestureRecognizerStateBegan == pinchGesture.state ||
      UIGestureRecognizerStateChanged == pinchGesture.state){

      //使用x或y比例,它们应该是相同的典型缩放(非倾斜)
      float currentScale = [[pinchGesture.view.layer valueForKeyPath:@transform.scale.x] floatValue];

      //用于调整zoom的最大/最小值的变量
      float minScale = 1.0;
      float maxScale = 2.0;
      float zoomSpeed = .5;

      float deltaScale = pinchGesture.scale;

      //你需要将缩放转换为0(原点),这样你
      //可以乘以一个速度因子然后转换回zoomSpace大约1
      deltaScale =((deltaScale - 1)* zoomSpeed)+ 1;

      //限制为最小/最大尺寸(即maxScale = 2,当前比例= 2,2 / 2 = 1.0)
      // deltaScale为〜0.99减少或~1.01增加
      // deltaScale为1.0将保持缩放尺寸
      deltaScale = MIN(deltaScale,maxScale / currentScale);
      deltaScale = MAX(deltaScale,minScale / currentScale);

      CGAffineTransform zoomTransform = CGAffineTransformScale(pinchGesture.view.transform,deltaScale,deltaScale);
      pinchGesture.view.transform = zoomTransform;

      //为比例增量
      重置为1 //注意:不是0,否则我们看不到大小:0 * width = 0
      pinchGesture.scale = 1 ;
      }
      }

      - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
      return YES; //适用于大多数用例的捏+变焦+平底锅
      }




    资源




    I am struggling a bit trying to figure out if it is possible to create a single combined gesture recognizer that combines UIPinchGestureRecognizer with UIPanGestureRecognizer.

    I am using pan for view translation and pinch for view scaling. I am doing incremental matrix concatenation to derive a resultant final transformation matrix that is applied to the view. This matrix has both scale and translation. Using separate gesture recognizers leads to a jittery movement/scaling. Not what I want. Thus, I want to handle concatenation of scale and translation once within a single gesture. Can someone please shed some light on how to do this?

    解决方案

    6/14/14: Updated Sample Code for iOS 7+ with ARC.

    The UIGestureRecognizers can work together and you just need to make sure you don't trash the current view's transform matrix. Use the CGAffineTransformScale method and related methods that take a transform as input, rather than creating it from scratch (unless you maintain the current rotation, scale, or translation yourself.

    Download Xcode Project

    Note: iOS 7 behaves weird with UIView's in IB that have Pan/Pinch/Rotate gestures applied. iOS 8 fixes it, but my workaround is to add all views in code like this code example.

    Demo Video

    1. Add them to a view and conform to the UIGestureRecognizerDelegate protocol

      @interface ViewController () <UIGestureRecognizerDelegate>
      
      @end
      
      @implementation ViewController
      
      - (void)viewDidLoad
      {
          [super viewDidLoad];
      
          UIView *blueView = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 150, 150)];
          blueView.backgroundColor = [UIColor blueColor];
          [self.view addSubview:blueView];
          [self addMovementGesturesToView:blueView];
      
          // UIImageView's and UILabel's don't have userInteractionEnabled by default!
          UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"BombDodge.png"]]; // Any image in Xcode project
          imageView.center = CGPointMake(100, 250);
          [imageView sizeToFit];
          [self.view addSubview:imageView];
          [self addMovementGesturesToView:imageView];
      
          // Note: Changing the font size would be crisper than zooming a font!
          UILabel *label = [[UILabel alloc] init];
          label.text = @"Hello Gestures!";
          label.font = [UIFont systemFontOfSize:30];
          label.textColor = [UIColor blackColor];
          [label sizeToFit];
          label.center = CGPointMake(100, 400);
          [self.view addSubview:label];
          [self addMovementGesturesToView:label];
      }
      
      - (void)addMovementGesturesToView:(UIView *)view {
          view.userInteractionEnabled = YES;  // Enable user interaction
      
          UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGesture:)];
          panGesture.delegate = self;
          [view addGestureRecognizer:panGesture];
      
          UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinchGesture:)];
          pinchGesture.delegate = self;
          [view addGestureRecognizer:pinchGesture];
      }
      

    2. Implement gesture methods

      - (void)handlePanGesture:(UIPanGestureRecognizer *)panGesture {
          CGPoint translation = [panGesture translationInView:panGesture.view.superview];
      
          if (UIGestureRecognizerStateBegan == panGesture.state ||UIGestureRecognizerStateChanged == panGesture.state) {
              panGesture.view.center = CGPointMake(panGesture.view.center.x + translation.x,
                                                   panGesture.view.center.y + translation.y);
              // Reset translation, so we can get translation delta's (i.e. change in translation)
              [panGesture setTranslation:CGPointZero inView:self.view];
          }
          // Don't need any logic for ended/failed/canceled states
      }
      
      - (void)handlePinchGesture:(UIPinchGestureRecognizer *)pinchGesture {
      
          if (UIGestureRecognizerStateBegan == pinchGesture.state ||
              UIGestureRecognizerStateChanged == pinchGesture.state) {
      
              // Use the x or y scale, they should be the same for typical zooming (non-skewing)
              float currentScale = [[pinchGesture.view.layer valueForKeyPath:@"transform.scale.x"] floatValue];
      
              // Variables to adjust the max/min values of zoom
              float minScale = 1.0;
              float maxScale = 2.0;
              float zoomSpeed = .5;
      
              float deltaScale = pinchGesture.scale;
      
              // You need to translate the zoom to 0 (origin) so that you
              // can multiply a speed factor and then translate back to "zoomSpace" around 1
              deltaScale = ((deltaScale - 1) * zoomSpeed) + 1;
      
              // Limit to min/max size (i.e maxScale = 2, current scale = 2, 2/2 = 1.0)
              //  A deltaScale is ~0.99 for decreasing or ~1.01 for increasing
              //  A deltaScale of 1.0 will maintain the zoom size
              deltaScale = MIN(deltaScale, maxScale / currentScale);
              deltaScale = MAX(deltaScale, minScale / currentScale);
      
              CGAffineTransform zoomTransform = CGAffineTransformScale(pinchGesture.view.transform, deltaScale, deltaScale);
              pinchGesture.view.transform = zoomTransform;
      
              // Reset to 1 for scale delta's
              //  Note: not 0, or we won't see a size: 0 * width = 0
              pinchGesture.scale = 1;
          }
      }
      
      - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
          return YES; // Works for most use cases of pinch + zoom + pan
      }
      

    Resources

    这篇关于UIPinchGestureRecognizer和UIPanGestureRecognizer可以合并吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆