13

Tôi muốn thêm chức năng vào các nút quay lại của mình thông qua ứng dụng dựa trên UINavigationController của tôi khi nhấn và giữ nút quay lại sẽ bật lên gốc. Tuy nhiên, tôi không thể tìm ra nơi để gắn trình nhận dạng cử chỉ. Tôi có phân lớp UINavigationBar và thử và phát hiện xem báo chí dài có nằm trong vùng nút trái không?phát hiện báo chí dài trên nút quay lại của UINavigationItem

Tôi đã nghe nói về những người thêm chức năng tương tự trước đây. Ai có ý tưởng gì không?

Trả lời

6

Tôi tin rằng UIGestureRecognizers chỉ có thể được thêm vào UIViews và các lớp con của UIViews.

http://developer.apple.com/library/ios/#documentation/uikit/reference/UIView_Class/UIView/UIView.html

Các nút quay lại là một UIBarButtonItem mà xuống từ NSObject. Do đó, bạn sẽ không thể đính kèm trình nhận dạng cử chỉ vào nút quay lại tiêu chuẩn bằng cách sử dụng

UILongPressGestureRecognizer *longPressGesture = 
      [[[UILongPressGestureRecognizer alloc] 
       initWithTarget:self action:@selector(longPress:)] autorelease]; 

[self.navigationItem.backBarButtonItem addGestureRecognizer:longPressGesture]; 

Tuy nhiên, bạn có thể thêm chế độ xem tùy chỉnh vào UIBarButtonItem. Một giao diện tùy chỉnh có thể chỉ là một cách dễ dàng là một UIView, UIButton, UILabel vv

Ví dụ:

UIView *myTransparentGestureView = [[UIView alloc] initWithFrame:CGRectMake(0,0,40,30)]; 
[myTransparentGestureView addGestureRecognizer:longPressGesture]; 
[self.navigationItem.backBarButtonItem setCustomView:myTransparentGestureView]; 
// Or you could set it like this 
// self.navigationItem.backBarButtonItem.customView = myTransparentGestureView; 
[myTransparentGestureView release]; 

Bạn phải cẩn thận tuy nhiên, vì tính thiết lập trên backBarButtonItem áp dụng đối với quan điểm tiếp theo mà bạn đẩy . Vì vậy, nếu bạn đã xem A đẩy để xem B và bạn muốn cử chỉ được nhận dạng khi bạn nhấn lại trong chế độ xem B. Bạn phải thiết lập nó trong chế độ xem A.

+0

Thêm một nhận dạng cử chỉ với một giao diện tùy chỉnh trên backButtomItem didn 't làm việc cho tôi ... người thừa nhận từ chối bắn. Bạn có thể làm cho nó hoạt động với mã ở trên không? – kevboh

+0

Có thể không hoạt động vì backBarButtonItem chỉ đọc, vì vậy nó không chấp nhận chế độ xem tùy chỉnh.Bạn rất có thể cần phải tạo ra leftbarbuttonitem của riêng bạn như câu trả lời này. http://stackoverflow.com/questions/526520/how-to-create-backbarbuttomitem-with-custom-view-for-a-uinavigationcontroller – Andrew

+0

Ah, nhưng sau đó tôi bị mất mũi tên quay lại trừ khi tôi tìm thấy hình ảnh ... có thể không đáng. Cảm ơn dù sao, mặc dù! – kevboh

15

Tôi biết câu hỏi này là cũ, nhưng tôi đã đến với một giải pháp. Thay vì cố gắng thêm công cụ nhận dạng cử chỉ vào nút (điều này sẽ là lý tưởng), tôi đã thêm nó vào self.navigationController.navigationBar và sau đó trong phương thức hành động, hãy sử dụng locationInView để xem liệu tôi có vượt qua nút quay lại hay không. Tôi đã không hoàn toàn chắc chắn về cách xác định nút quay lại chính xác, vì vậy tôi vụng về chỉ cần lấy các subview đầu tiên với một tọa độ x ít hơn một số giá trị tùy ý, nhưng nó có vẻ đầy hứa hẹn. Nếu ai đó có cách tốt hơn để xác định khung của nút quay lại, hãy cho tôi biết.

- (void)longPress:(UILongPressGestureRecognizer *)sender 
{ 
    if (sender.state == UIGestureRecognizerStateEnded) 
    { 
     // set a default rectangle in case we don't find the back button for some reason 

     CGRect rect = CGRectMake(0, 0, 100, 40); 

     // iterate through the subviews looking for something that looks like it might be the right location to be the back button 

     for (UIView *subview in self.navigationController.navigationBar.subviews) 
     { 
      if (subview.frame.origin.x < 30) 
      { 
       rect = subview.frame; 
       break; 
      } 
     } 

     // ok, let's get the point of the long press 

     CGPoint longPressPoint = [sender locationInView:self.navigationController.navigationBar]; 

     // if the long press point in the rectangle then do whatever 

     if (CGRectContainsPoint(rect, longPressPoint)) 
      [self doWhatever]; 
    } 
} 

- (void)addLongPressGesture 
{ 
    if (NSClassFromString(@"UILongPressGestureRecognizer")) 
    { 
     UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)]; 
     [self.navigationController.navigationBar addGestureRecognizer:longPress]; 
     [longPress release]; 
    } 
} 
+0

Ý tưởng hay. Lần tới tôi cần làm điều này tôi sẽ thử cách tiếp cận của bạn. Cảm ơn đã theo lên! – kevboh

+0

Tôi ổn với chỉ bất kỳ báo chí dài ở đó để bật - có vẻ hợp lý với tôi. –

+0

Tôi đã có yêu cầu tương tự như thiết lập một cử chỉ longPress trên nút quay lại. Vấn đề với cách tiếp cận này là nút quay lại không còn trong trạng thái được tô sáng. Vì vậy, tôi đặt cancelsTouchesInView thích hợp với NO.BUt, sau đó cả trình xử lý longPressHandler và backButton của tôi được gọi là. Bất kỳ giải pháp cho điều này ?? – user1010819

3

Tôi đã đi theo một con đường hơi khác một chút, tôi đã chia sẻ nó. Những câu trả lời trên là tốt, nhưng thực sự, nếu báo chí dài là trong 1/3 hàng đầu của thanh nav, đó là đủ tốt cho tôi:

- (void)longPress:(UILongPressGestureRecognizer *)gr 
{ 
    NSLog(@"longPress:"); 
    UINavigationBar *navBar = [self navigationBar]; 
    CGFloat height = navBar.bounds.size.height; 
    CGPoint pt = [gr locationOfTouch:0 inView:navBar]; 
    //NSLog(@"PT=%@ height=%f", NSStringFromCGPoint(pt), height); 
    if(CGRectContainsPoint(CGRectMake(0,0,100,height), pt)) { 
     [self popToViewController:self.viewControllers[0] animated:YES]; 
    } 
} 
0

Đây là giải pháp của tôi:

Trong appdelegate (các "chủ sở hữu" của thanh nav trong ứng dụng của tôi), trong applicationDidFinishLaunchingWithOptions:

Lấy cái nhìn thanh nav và thêm các nhận dạng cử chỉ cho toàn bộ quan điểm:

// Get the nav bar view 
UINavigationBar *myNavBar = nil; 
for (UIView *view in [self.window.rootViewController.view subviews]) { 
    if ([view isKindOfClass:[UINavigationBar class]]) { 
     NSLog(@"Found Nav Bar!!!"); 
     myNavBar = (UINavigationBar *)view; 
    } 
} 

UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self 
                         action:@selector(backButtonLongPress:)]; 
[myNavBar addGestureRecognizer:longPress]; 
NSLog(@"Gesture Recognizer Added."); 

Sau đó, trong appDel eGate, trong - (void) backButtonLongPress: (id) sender

Kiểm tra để xem nếu cử chỉ xảy ra trong khuôn khổ các nút quay lại:

if ([sender state] == UIGestureRecognizerStateBegan) { 

    // Get the nav bar view 
    UINavigationBar *myNavBar = nil; 
    for (UIView *view in [self.window.rootViewController.view subviews]) { 
     if ([view isKindOfClass:[UINavigationBar class]]) { 
      NSLog(@"Found Nav Bar!!!"); 
      myNavBar = (UINavigationBar *)view; 
     } 
    } 

    // Get the back button view 
    UIView *backButtonView = nil; 
    for (UIView *view in [myNavBar subviews]) { 
     if ([[[view class] description] isEqualToString:@"UINavigationItemButtonView"]) { 
      backButtonView = view; 
      NSLog(@"Found It: %@", backButtonView); 
      NSLog(@"Back Button View Frame: %f, %f; %f, %f", backButtonView.frame.origin.x, backButtonView.frame.origin.y, backButtonView.frame.size.width, backButtonView.frame.size.height); 
     } 
    } 

    CGPoint longPressPoint = [sender locationInView:myNavBar]; 
    NSLog(@"Touch is in back button: %@", CGRectContainsPoint(backButtonView.frame, longPressPoint) ? @"YES" : @"NO"); 
    if (CGRectContainsPoint(backButtonView.frame, longPressPoint)) { 
     // Place your action here 
    } 

    // Do nothing if outside the back button frame 

}