2012-06-10 100 views
1

我在放大屏幕時遇到uipangesturerecognizer問題。當我放大屏幕時,UIPanGestureRecognizer無法正常工作

我的應用程序有一個uiview的uiviewcontroller。

在這個視圖中,我有一個幾乎是整個屏幕邊界一半的calayer。

該calayer有幾個子層,用戶可以拖動(uipangesture),添加(uitapgesture)和刪除(doubletapgesture)。爲了更準確地拖動我添加到uiview的一個uipinchgesture方法來放大和縮小。

在這一點上,除了當我放大並嘗試移動(pangesture)子圖層時,一切都很好。有時工作,但通常不(沒有放大總是工作正常)。

我不知道我的密碼是否有問題,或者可能不是這樣做的。有什麼我想念的嗎?

我在sdk 4.2下。

這些都是我的代碼:

 
    - (id)initWithFrame:(CGRect)frame 
    { 
     [super initWithFrame:frame]; 
     (…) 
     perfil = [[CALayer alloc] init];  //the calayer of the uiview 
     [perfil setBounds:CGRectMake(0, 0, wide, heigth/2)]; 
     [[self layer] addSublayer:perfil]; 

     //I add the sublayers to the "peril" layer when the user touch an "edit button" and that works fine 

     //UIGsture Recognizers 
     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 requireGestureRecognizerToFail:doubleTapRecognizer]; 
     singleTapRecognizer.delegate = self; 
     doubleTapRecognizer.delegate = self; 
     pinchGestureRecognizer.delegate = self; 
     panGestureRecognizer.delegate = self; 

     //Some other different stuff here 
    } 

 

    - (void) handlePanFrom: (id)sender 
    { 
     CGPoint point = [(UIPanGestureRecognizer*)sender locationInView:self]; 
     boxLayer = [[self perfil] hitTest:point]; 
     [self becomeFirstResponder]; 

     if([(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateBegan) 
     { 
      numberOfSublayer = 1000; //declared as a int in UIView.h 

      for (CALayer *elements in [perfil sublayers]) 
      { 
       if([boxLayer isEqual:elements]) 
       { 
        numberOfSublayer = [[perfil sublayers] indexOfObject:elements]; 
        break; 
       } 
      } 
     } 
     (…) //Some more operations once I found the sublayer 
    } 

 

    - (void) handlePinchFrom: (id)sender 
    { 
     if([(UIPinchGestureRecognizer*)sender state] == UIGestureRecognizerStateEnded) 
     { 
      lastScale = 1.0; 
      return; 
     } 

     if ([(UIPinchGestureRecognizer*)sender state] == UIGestureRecognizerStateBegan || 
      [(UIPinchGestureRecognizer*)sender state] == UIGestureRecognizerStateChanged) { 

      CGFloat currentScale = [[[sender view].layer valueForKeyPath:@"transform.scale"] floatValue]; 

      const 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); 
      [sender view].transform = transform; 

      if ([perfil sublayers]) 
      { 
       for (CALayer *elements in [perfil sublayers]) //Here I try to adjust the zoom to the sublayers 
       { 
        //Here is one first approach 
        //CGAffineTransform transformELS = CGAffineTransformScale([elements affineTransform], 7/(newScale+6), 7/(newScale+6)); 
        //[elements setAffineTransform:transformELS]; 

        //Here is a second approach 
        [elements setBounds:CGRectMake(0, 0, elements.bounds.size.width*7/(newScale+6), elements.bounds.size.height*7/(newScale+6))]; 
       }   
      } 

      lastScale = [(UIPinchGestureRecognizer*)sender scale]; 
      (…) //Some other different stuff here 
    } 

非常感謝你。

回答

0

真的很難說,沒有看到子層的測試代碼,但它看起來很奇怪,你重新縮放父視圖/層時重新調整子層。

你應該只需要縮放父層,所有的孩子都會依次縮放。

所有這些手動生成捏和平底鍋的代碼是充滿危險。它可以完成,但我發現你最終與意大利麪條。

將您的視圖放在UIScrollView中,讓它執行捏合和平移perfil視圖的工作。

Theres十億例子的UIScrollView平移和縮放。如果你還沒有,Google和SO會知道。

我期望捕獲在父視圖的touchBegan事件中的子圖層平移。

這是我使用父視圖的的touchesBegan/touchesMoved捕獲命中一個子層

- (CALayer *)hitTest:(CGPoint)thepoint 
{ 
    // 
    CGPoint cpoint = [self convertPoint:thepoint fromLayer:self.superlayer]; 

    if (CGRectContainsPoint([self bounds], cpoint)) { 
     NSLog(@"hitme!"); 
     return self; 
    } 

    return nil; 

} 

這。 (請保留對scrollview的弱引用)

// 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 


} 

該代碼既不完整也未檢查錯誤,但應讓您關閉。

+0

謝謝沃倫的評論。我使用的子層次測試代碼是我沒有編碼的標準測試代碼([[self perfil] hitTest:point])。你沒有擴展子層是正確的,那是一個試圖找到問題的測試代碼。我從來沒有實現過這些手勢或滾動方法,我對他們都很困惑,主要是因爲我正在處理CALayers而不是UIViews以及我在滾動視圖中看到的所有代碼。我認爲我的代碼應該可行,最終我會檢查您的建議和您提出的代碼,這可能是一種簡單的方法。 – Kanick

相關問題