17

Tôi muốn kết hợp một UILongPressGestureRecognizer với một UIPanGestureRecognizer.Kết hợp một UILongPressGestureRecognizer với một UIPanGestureRecognizer

UIPanGestureBộ nhận dạng nên bắt đầu bằng báo chí dài. Có một cách đơn giản để làm điều này? hoặc tôi có thực sự phải viết trình nhận dạng cử chỉ của riêng mình không?

Tôi không giống như trên màn hình chính. Bạn bấm vào một biểu tượng và sau một thời gian các biểu tượng bắt đầu lung lay. Sau đó mà không thả ngón tay của tôi ra khỏi màn hình, tôi có thể bắt đầu kéo biểu tượng dưới ngón tay của tôi xung quanh.

Trả lời

16

Tôi tìm thấy một giải pháp: phương pháp UIGestureRecognizerDelegate này thực hiện chính xác những gì tôi đã tìm kiếm:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer 
shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer 
20

trên thực tế, bạn không cần phải kết hợp recognizers cử chỉ - bạn có thể làm được điều này chỉ với UILongPressGestureRecognizer ... Bạn nhập StateBegan sau khi (các) liên lạc của bạn đã ở trong 'allowableMovement' cho 'minimumPressDuration'. Bạn ở trong longPressGesture liên tục của bạn miễn là bạn không nhấc bất kỳ ngón tay của bạn - vì vậy bạn có thể bắt đầu di chuyển các ngón tay của bạn và theo dõi chuyển động thông qua StateChanged.

Cử chỉ báo chí dài liên tục. Cử chỉ bắt đầu (UIGestureRecognizerStateBegan) khi số lượng ngón tay cho phép (numberOfTouchesRequired) đã được nhấn trong khoảng thời gian được chỉ định (minimumPressDuration) và các điểm chạm không di chuyển vượt quá phạm vi cho phép di chuyển (allowableMovement). Trình nhận dạng cử chỉ chuyển sang trạng thái Thay đổi bất cứ khi nào một ngón tay di chuyển và nó kết thúc (UIGestureRecognizerStateEnded) khi bất kỳ ngón tay nào được nhấc lên.

+3

Có nhiều vấn đề bạn có thể gặp phải. Một trong những điều tốt nhất về UIPanGestureRecognizer là nó cho phép bạn xoay toàn bộ cửa sổ và vẫn trả về các giá trị, trong khi UILongPressGestureRecognizer không để lại các bản xem trước (ít nhất là với ClipsToBounds) – Kpmurphy91

+1

Ngoài ra, không có 'vận tốc' khi bạn di chuyển một LongPress –

15

Tôi đã có một chút thời gian khó khăn cho vấn đề này. Câu trả lời được chấp nhận là không đủ. Không có vấn đề gì tôi đưa vào phương pháp đó các pan hoặc xử lý longpress sẽ được gọi. Giải pháp tôi tìm thấy như sau:

  1. Đảm bảo các đại biểu nhận dạng cử chỉ được gán cho cùng một lớp (trong trường hợp của tôi) và đảm bảo lớp đại biểu là UIGestureRecognizerDelegate.
  2. Thêm phương pháp đại biểu sau để lớp học của bạn (theo câu trả lời ở trên):

    - (BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer 
    shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { 
        return YES; 
    } 
    
  3. Thêm phương pháp đại biểu sau để lớp học của bạn:

    - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer { 
        if([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] && ! shouldAllowPan) { 
          return NO; 
        } 
        return YES; 
    } 
    
  4. Sau đó thêm hoặc là một tài sản hoặc ivar sẽ theo dõi nếu chảo được phép bắt đầu (xem phương pháp trên). Trong trường hợp của tôi BOOL shouldAllowPan.

  5. Đặt BOOL thành NO trong init hoặc viewDidLoad. Bên trong trình xử lý longPress của bạn đặt BOOL thành YES.Tôi làm điều đó như thế này:

    - (void) longPressHandler: (UILongPressGestureRecognizer *) gesture { 
    
        if(UIGestureRecognizerStateBegan == gesture.state) { 
         shouldAllowPan = NO; 
        } 
    
        if(UIGestureRecognizerStateChanged == gesture.state) { 
         shouldAllowPan = YES; 
        } 
    } 
    
  6. Bên Gã ăn mày tôi làm một kiểm tra về BOOL:

    - (void)panHandler:(UIPanGestureRecognizer *)sender{ 
        if(shouldAllowPan) { 
          // do your stuff 
        } 
    
  7. Và cuối cùng reset BOOL trong vòng Gã ăn mày:

    else if(sender.state == UIGestureRecognizerStateEnded || sender.state == UIGestureRecognizerStateFailed || sender.state == UIGestureRecognizerStateCancelled) { 
        shouldAllowPan = NO; 
    } 
    
  8. Và sau đó đi lấy một ly bia để chúc mừng bản thân. ;)

+1

+1. Các bước này thực sự đã giúp tôi giải quyết mục tiêu của op: chỉ cho phép kéo sau khi nhấn và giữ. Chỉ cần 2 chú thích: ở bước 5 là đủ để kiểm tra 'Bắt đầu' và sau đó đặt thành' CÓ'. '' ' \t if (UIGestureRecognizerStateBegan == gesture.state) { \t \t self.shouldAllowDrag = YES; \t} '' ' Và ở bước 6. không cần phải kiểm tra' shouldAllowPan'. - xin lỗi vì mã chưa định dạng. –

+1

Tôi đã triển khai giải pháp của Andy và nó hoạt động rất tốt. Để có được sự đáp ứng mà tôi muốn, tôi cũng đã thay đổi thời lượng báo chí dài tối thiểu: UILongPressGestureRecognizer * lpgr = [[UILongPressGestureRecognizer alloc] initWithTarget: tự hành động: @selector (handleLongPressGesture :)]; lpgr.delegate = tự; lpgr.minimumPressDuration = 0,05; – chmaynard

+1

Điều này đã giúp tôi rất nhiều. Cảm ơn! Tôi sẽ thêm vào một giải pháp Swift để nó có thể giúp người khác. – duyn9uyen

5

cách tiếp cận Andy B ở Swift,

  1. Thêm UIGestureRecognizerDelegate đại biểu đến lớp

    class ViewController: UIViewController, UIGestureRecognizerDelegate 
    
  2. Thêm một biến thành viên

    var shouldAllowPan: Bool = false 
    
  3. Thêm cử chỉ và cần thêm đại biểu cử chỉ pan vào VC. Này là cần thiết để bắn ra các chức năng shouldRecognizeSimultaneouslyWithGestureRecognizer và gestureRecognizerShouldBegin

    // long press 
    let longPressRec = UILongPressGestureRecognizer(target: self, action: "longPress:") 
    yourView.addGestureRecognizer(longPressRec) 
    
    // drag 
    let panRec = UIPanGestureRecognizer(target: self, action: "draggedView:") 
    panRec.delegate = self 
    yourView.addGestureRecognizer(panRec) 
    
  4. phép cử chỉ đồng thời

    func gestureRecognizer(UIGestureRecognizer, 
    shouldRecognizeSimultaneouslyWithGestureRecognizer:UIGestureRecognizer) -> Bool { 
        // println("shouldRecognizeSimultaneouslyWithGestureRecognizer"); 
        return true 
    } 
    
    func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool { 
        // We only allow the (drag) gesture to continue if it is within a long press 
        if((gestureRecognizer is UIPanGestureRecognizer) && (shouldAllowPan == false)) { 
         return false; 
        } 
        return true; 
    } 
    
  5. Bên trong xử lý báo chí dài:

    func longPress(sender: UILongPressGestureRecognizer) { 
    
        if(sender.state == .Began) { 
         // handle the long press 
        } 
        else if(sender.state == .Changed){ 
         shouldAllowPan = true 
    
        } 
        else if (sender.state == .Ended) { 
         shouldAllowPan = false 
        } 
    } 
    
+3

Bạn đã quên 6.Lấy một ly bia. :) :) –

+1

@ duyn9uyen Cảm ơn bạn đã chuyển đổi nó sang Swift. –

+0

@ duyn9uyen Cảm ơn bạn đã chuyển đổi và điều này hoạt động như một sự quyến rũ. – aznelite89

0

Đọc "subclassing Ghi chú "phần giao diện người dùng của Apple Tham chiếu lớp GestureRecognizer tại:

Các vấn đề liên quan