2012-03-20 39 views
10

我想攔截UITextview上的長按,但不想同時禁用上下文菜單選項。如何在不禁用上下文菜單的情況下攔截UITextView上的長按?

如果我在textview上使用手勢識別器,它將禁用上下文菜單,所以我現在使用下面的方法。

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {  
    //fire my method here 
} 

但是,它只有在上下文菜單中用戶長按後,就可以看出一些話觸發的方法。所以當用戶長時間按住空白處時,只有放大鏡出現,當時我無法啓動該方法。

有沒有人有更好的想法?謝謝!

//////的問題就迎刃而解了//////

感謝@danh和@Beppe,我甚至對UITextView的叩擊手勢做到了。我想通過長按在textview上顯示字體欄。

@首先,我分類了UITextview。

@interface LisgoTextView : UITextView { 
    BOOL  pressing_; 

} 

@property (nonatomic)   BOOL  pressing; 

@end 


@interface LisgoTextView (private) 
    - (void)longPress:(UIEvent *)event; 
@end 


@implementation LisgoTextView 

@synthesize pressing = pressing_; 


//--------------------------------------------------------------// 
#pragma mark -- Long Press Detection -- 
//--------------------------------------------------------------// 

- (void)longPress:(UIEvent *)event { 

    if (pressing_) { 

     //post notification to show font edit bar 
     NSNotification *fontEditBarNotification = [NSNotification notificationWithName:@"fontEditBarNotification" 
                       object:nil userInfo:nil]; 
     [[NSNotificationCenter defaultCenter] postNotification:fontEditBarNotification]; 
    }  
} 

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
    [super touchesBegan:touches withEvent:event]; 
    [self performSelector:@selector(longPress:) withObject:event afterDelay:0.7]; 
    pressing_ = YES; 
} 

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 
    [super touchesEnded:touches withEvent:event];  
    pressing_ = NO; 
} 

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { 
    [super touchesMoved:touches withEvent:event];  
    pressing_ = NO; 
} 

@I使用延遲來解決我在UITextView上實現的輕拍手勢的衝突。

- (void)tapGestureOnTextView:(UITapGestureRecognizer *)sender { 

    //cancel here if long press was fired first 
    if (cancelTapGesture_) { 
     return; 
    } 

    //don't fire show font bar 
    cancelShowFontBar_ = YES; 
    [self performSelector:@selector(enableShowFontBar) withObject:nil afterDelay:1.0]; 

    //method here 
} 


- (void)showFontEditBar { 

    //cancel here if tap gesture was fired first 
    if (cancelShowFontBar_) { 
     return; 
    } 

    if (fontEditBarExists_ == NO) { 

     //method here  

     //don't fire tap gesture 
     cancelTapGesture_ = YES; 
     [self performSelector:@selector(enableTapGesture) withObject:nil afterDelay:1.0]; 
    } 
} 

- (void)enableTapGesture { 
    cancelTapGesture_ = NO; 
} 

- (void)enableShowFontBar { 
    cancelShowFontBar_ = NO; 
} 

回答

7

我通常會避免子類,除非文檔明確建議,這爲我工作。長按和上下文菜單。哎呀 - 只是由@Beppe加載的答案。偉大的思想家都認爲:-)

@interface TextViewSubclass() 
@property(assign,nonatomic) BOOL pressing; 
@end 

@implementation TextViewSubclass 
@synthesize pressing=_pressing; 

- (void)longPress:(UIEvent *)event { 
    NSLog(@"long press"); 
} 

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
    [super touchesBegan:touches withEvent:event]; 
    self.pressing = YES; 
    [self performSelector:@selector(longPress:) withObject:event afterDelay:2.0]; 
} 

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 
    [super touchesEnded:touches withEvent:event]; 
    [NSObject cancelPreviousPerformRequestsWithTarget:self]; 
    self.pressing = NO; 
} 
@end 
+0

ahahah:D Banzai爲「偉大的思想」! – Beppe 2012-03-20 15:04:42

+0

即使我仍在努力解決與在UITextview上實現的tapGesture衝突,這是我的問題的答案。非常感謝你。 – 2012-03-20 16:40:39

+0

我在衝突中做了這個,所以在答案部分寫下了工作上的缺陷。 – 2012-03-21 07:27:58

0

您可以使用UITextViewDelegate協議的textViewDidChangeSelection方法?

+0

我相信我需要選擇文本來截取它。 :( – 2012-03-20 16:42:48

+0

好吧,這是一個很長的一次... – 2012-03-23 13:31:33

2

這有點棘手,但它適用於我。

我加上我的UITextView的頂部的UIButton的子類,檢查是否有長期接觸,並通過他們的UITextView這樣:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
    [super touchesBegan:touches withEvent:event]; 
    isLongTouchDetected = NO; 
    [self performSelector:@selector(longTouchDetected) withObject:nil afterDelay:1.0]; 
} 

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 
    if (isLongTouchDetected == YES) { 
     [super touchesCancelled:touches withEvent:event]; 
    } else { 
     [super touchesEnded:touches withEvent:event]; 
     [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(longTouchDetected) object:nil]; 
    } 
} 

- (void)longTouchDetected { 
    isLongTouchDetected = YES; 
    // pass long touch to UITextView 
} 
+0

我還沒有嘗試過這種方式,因爲我是UITextview的子類。但是,這一定也會起作用。謝謝。 – 2012-03-20 16:42:09

+0

不客氣! – Beppe 2012-03-20 17:49:42

4

這對我有效。我只是想控制當用戶點擊或長按一個鏈接

- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange 
{ 
    // check for long press event 
    BOOL isLongPress = YES; 
    for (UIGestureRecognizer *recognizer in self.commentTextView.gestureRecognizers) { 
     if ([recognizer isKindOfClass:[UILongPressGestureRecognizer class]]){ 
      if (recognizer.state == UIGestureRecognizerStateFailed) { 
       isLongPress = NO; 
      } 
     } 
    } 

    if (isLongPress) { 
     // user long pressed a link, do something 
    } else { 
     // user tapped on a link, do something 
    } 

    // return NO cause you dont want the normal behavior to occur 
    return NO; 
} 
+0

聰明的解決方案! – Johnny 2015-06-16 22:58:47

+0

這對我來說在iOS 9中是失敗的。當NSLogging識別器出現'Failed'狀態時出現一個新的神祕識別器。 我將邏輯切換到至少一個「開始」狀態的長按識別器。仍然有點ha,,但現在在iOS 8和9上工作。 請參閱下面的新代碼(單獨發佈以便能夠格式化代碼)。 – chr 2015-09-24 19:53:35

+0

我認爲這不起作用的原因是'UIPreviewGestureRecognizer',它是'UILongPressGestureRecognizer'的子類,並且一個失敗。所以我認爲,而不是'isKindOfClass'只是使用'isMemberOfClass'來不檢查子類。 – josip04 2017-06-13 09:39:05

3

適應盧卡斯Chwe的回答在iOS 9工作所發生的(8)。在他的回答中看到評論。

要點:通過以「不長按」開始反轉邏輯,如果至少有一個UILongPressGestureRecognizer處於Began狀態,則切換到「長按檢測」。

BOOL isLongPress = NO; 
for (UIGestureRecognizer *recognizer in textView.gestureRecognizers) { 
    if ([recognizer isKindOfClass:[UILongPressGestureRecognizer class]]) { 
     if (recognizer.state == UIGestureRecognizerStateBegan) { 
      isLongPress = YES; 
     } 
    } 
} 

還是有些黑客,但現在在iOS 8和9上工作。

0

對於SWIFT [最簡單的方法]

extension UITextField { 

    override public func canPerformAction(action: Selector, withSender sender: AnyObject?) -> Bool { 
     if action == "paste:" { 
      return false 
     } 

     return super.canPerformAction(action, withSender: sender) 
    } 

    override public func addGestureRecognizer(gestureRecognizer: UIGestureRecognizer) { 
     if gestureRecognizer.isKindOfClass(UILongPressGestureRecognizer) { 
      gestureRecognizer.enabled = false 
     } 
     super.addGestureRecognizer(gestureRecognizer) 
     return 
    } 
} 

上面的代碼也功能在內容菜單禁用「粘貼」選項。

相關問題