【问题标题】:UIPanGestureRecognizer does not work when I zoom in放大时 UIPanGestureRecognizer 不起作用
【发布时间】:2012-06-13 15:03:00
【问题描述】:

我在放大屏幕时遇到了 uipangesturerecognizer 问题。

我的应用有一个带有 uiview 的 uiviewcontroller。

在这个视图中,我有一个几乎占整个屏幕边界一半的 calayer。

这个 calayer 有几个子层,用户可以拖动 (uipangesture)、添加 (uitapgesture) 和删除 (doubletapgesture)。为了更准确地拖动,我在 uiview 中添加了一个 uipinchgesture 方法来放大和缩小。

此时一切正常,除非我放大并尝试移动(pangesture)子图层。有时有效,但通常无效(不放大总是可以正常工作)。

我不知道我的代码是否有问题,或者可能不是这样做的方法。有什么我想念的吗?

我在 sdk 4.2 下。

这些是我的代码:

- (id)initWithFrame:(CGRect)frame { [超级 initWithFrame:frame]; (……) perfil = [[CALayer alloc] init]; //uiview的图层 [perfil setBounds:CGRectMake(0, 0, wide, heigth/2)]; [[自层] addSublayer:perfil]; //当用户触摸“编辑按钮”时,我将子层添加到“危险”层,效果很好 //UIGsture 识别器 UITapGestureRecognizer *singleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTapFrom:)]; UITapGestureRecognizer *doubleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDoubleTapFrom:)]; UIPinchGestureRecognizer *pinchGestureRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinchFrom:)]; UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanFrom:)]; [panGestureRecognizer setMinimumNumberOfTouches:1]; [panGestureRecognizer setMaximumNumberOfTouches:1]; [singleTapRecognizer setNumberOfTapsRequired:1]; [singleTapRecognizer setCancelsTouchesInView:NO]; [doubleTapRecognizer setNumberOfTapsRequired:2]; [self addGestureRecognizer:singleTapRecognizer]; [self addGestureRecognizer:doubleTapRecognizer]; [self addGestureRecognizer:pinchGestureRecognizer]; [self addGestureRecognizer:panGestureRecognizer]; [singleTapRecognizer 需要GestureRecognizerToFail:doubleTapRecognizer]; singleTapRecognizer.delegate = self; doubleTapRecognizer.delegate = self; pinchGestureRecognizer.delegate = self; panGestureRecognizer.delegate = self; //这里有一些其他不同的东西 } - (void) handlePanFrom: (id)sender { CGPoint 点 = [(UIPanGestureRecognizer*)sender locationInView:self]; boxLayer = [[self perfil] hitTest:point]; [自己成为FirstResponder]; if([(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateBegan) { numberOfSublayer = 1000; //在 UIView.h 中声明为 int for (CALayer *elements in [perfil sublayers]) { if([boxLayer isEqual:elements]) { numberOfSublayer = [[perfil sublayers] indexOfObject:elements]; 休息; } } } (…) //找到子层后的一些操作 } - (void) handlePinchFrom: (id)sender { if([(UIPinchGestureRecognizer*)sender state] == UIGestureRecognizerStateEnded) { lastScale = 1.0; 返回; } if ([(UIPinchGestureRecognizer*)sender state] == UIGestureRecognizerStateBegan || [(UIPinchGestureRecognizer*)sender state] == UIGestureRecognizerStateChanged) { CGFloat currentScale = [[[sender view].layer valueForKeyPath:@"transform.scale"] floatValue]; 常量 CGFloat kMaxScale = 4.0; const CGFloat kMinScale = 1.0; CGFloat newScale = 1 - (lastScale - [(UIPinchGestureRecognizer*)sender scale]); newScale = MIN(newScale, kMaxScale / currentScale); newScale = MAX(newScale, kMinScale / currentScale); CGAffineTransform transform = CGAffineTransformScale([[sender view] transform], newScale, newScale); [发送者视图].transform = transform; if ([perfil 子层]) { for (CALayer *elements in [perfil sublayers]) //这里我尝试调整缩放到子层 { //这是第一种方法 //CGAffineTransform transformELS = CGAffineTransformScale([元素 affineTransform], 7/(newScale+6), 7/(newScale+6)); //[元素setAffineTransform:transformELS]; //这里是第二种方法 [元素设置边界:CGRectMake(0, 0, elements.bounds.size.width*7/(newScale+6), elements.bounds.size.height*7/(newScale+6))]; } } lastScale = [(UIPinchGestureRecognizer*)sender scale]; (...) //这里有一些其他不同的东西 }

非常感谢。

【问题讨论】:

    标签: iphone zooming uipangesturerecognizer


    【解决方案1】:

    我终于找到了问题的答案。这篇文章解释了完全相同的问题,它的解决方案对我来说非常有效 UIPanGestureRecognizer starting point is off 。谢谢。

    【讨论】:

      【解决方案2】:

      如果没有看到子层 hittest 代码,真的很难说,但是当您重新缩放父视图/层时,您正在重新缩放子层似乎真的很奇怪。

      您应该只需要缩放父图层,所有子图层将依次缩放。

      所有这些手动生成的捏和平移代码都充满了危险。可以做到,但我发现你最后吃的是意大利面。

      将您的视图放在 UIScrollView 中,让它完成perfil 视图的捏合和平移工作。

      有十亿个 UIScrollView 平移和缩放示例。如果您还不知道,Google 和 SO 会知道。

      我希望在父视图的 touchBegan 事件中捕获子图层的平移。

      这是我用来在子层中捕获命中的方法

      - (CALayer *)hitTest:(CGPoint)thepoint
      {
          //
          CGPoint cpoint = [self convertPoint:thepoint fromLayer:self.superlayer];
      
          if (CGRectContainsPoint([self bounds], cpoint)) {
              NSLog(@"hitme!");
              return self;
          }
      
          return nil;
      
      }
      

      这在父视图的 touchesBegan/touchesMoved 中。 (保持对滚动视图的弱引用)

      // Handles the start of a touch
      - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
      {
      
      
          NSUInteger tcount = [touches count];
          if(tcount == 1)
          {
      
          UITouch* touch = [touches anyObject];
          CGPoint tpoint = [touch locationInView:self];
          location = [perfil convertPoint:tpoint fromLayer:view.layer];
      
          hitsublayer = [self hitTest:location];       
          if([hitsublayer isKindOfClass:[MySubBoxThing class]]){
              //ensure that scroll view doesn't capture the event  
              scrollview.canCancelContentTouches = NO;
          }
          else {
              hitsublayer = nil;
              //or something else to do wit not touching a sublayer.
          }
      
      }
      
      // Handles the continuation of a touch.
      - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
      {   
          NSUInteger tcount = [touches count];
          if (tcount == 1 && hitsublayer) {
      
          UITouch* touch = [touches anyObject];
          CGPoint tlocation = [touch locationInView:self];
          location = [perfil convertPoint:tpoint fromLayer:view.layer];        
      
          NSLog(@"new loc = %@",[NSValue valueWithCGPoint:location]);
          hitsublayer.position = location;            
      
          }       
      
      }
      
      // Handles the end of a touch event when the touch is a tap.
      - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
      {
          //NSLog(@"touches ended");
          scrollview.canCancelContentTouches = YES;
          hitsublayer = nil;
          //any other actions once finished drag of object
      
      
      }
      

      该代码既不完整也未检查错误,但应该让您接近。

      【讨论】:

      • 感谢 Warren 的 cmets。我使用的子层 hittest 代码是我没有编码的标准代码([[self perfil] hitTest:point])。关于不缩放子层,您是对的,那是试图找到问题的测试代码。我以前从未实现过这些手势或滚动方法,我对所有这些方法都很困惑,主要是因为我处理的是 CALayers 而不是 UIViews 以及我在滚动视图中看到的所有代码。我认为我的代码应该可以工作,最终我会检查您的建议和您提出的代码,这可能是一种简单的方法。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-23
      相关资源
      最近更新 更多