Iphone 如何在不禁用关联菜单的情况下拦截长按UITextView?
我想截取UITextview上的长按,但不想同时禁用关联菜单选项 如果我在textview上使用手势识别器,它将禁用上下文菜单,因此我现在使用下面的方法Iphone 如何在不禁用关联菜单的情况下拦截长按UITextView?,iphone,uitextview,uigesturerecognizer,Iphone,Uitextview,Uigesturerecognizer,我想截取UITextview上的长按,但不想同时禁用关联菜单选项 如果我在textview上使用手势识别器,它将禁用上下文菜单,因此我现在使用下面的方法 - (BOOL)canPerformAction:(SEL)action withSender:(id)sender { //fire my method here } 但是,它只在用户长按某些单词后出现上下文菜单时触发该方法。因此,当用户长按一个空格时,只有放大镜显示,此时我无法启动该方法 有人有更好的主意吗?谢谢 ////
- (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;
}
@我使用延迟来解决我在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;
}
您可以使用
UITextViewDelegate
协议的textViewDidChangeSelection
方法吗?这有点棘手,但对我来说很有效
我在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
}
我通常避免子类化,除非文档明确指出,这对我来说很有效。长按和上下文菜单。哎哟-回答刚刚由@Beppe加载。英雄所见略同:-)
这对我有用。我只是想控制当用户点击或长按链接时会发生什么
- (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;
}
将Lucas Chwe的答案改编为iOS 9(和iOS 8)。见他的回答中的评论 要点:从“no long press”(无长按)开始反转逻辑,然后如果至少有一个
UILongPressGestureRecognitor
处于Start
状态,则切换到“long press detected”(长按检测)
BOOL isLongPress = NO;
for (UIGestureRecognizer *recognizer in textView.gestureRecognizers) {
if ([recognizer isKindOfClass:[UILongPressGestureRecognizer class]]) {
if (recognizer.state == UIGestureRecognizerStateBegan) {
isLongPress = YES;
}
}
}
仍然有点老土,但现在正在为iOS 8和iOS 9工作。用于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
}
}
上面的代码还具有禁用内容菜单中“粘贴”选项的功能。尽管我仍在努力解决与在UITextview上实现的TapPaste的冲突,但这就是我问题的答案。非常感谢。我成功地解决了冲突,所以在答案部分写下了工作缺陷。我没有尝试过这种方法,因为我是UITextview的子类。但是,这也必须起作用。谢谢。我想我需要选择文本来截取它:(这对我来说在iOS 9中是失败的。当记录识别器时,有一个新的神秘识别器处于
失败
状态。我切换了逻辑,在开始
状态下寻找至少一个长按识别器。仍然有点黑客,但现在在iOS 8和9中工作。请参阅下面的文章,了解新代码。)(单独发布以便能够格式化代码)。我认为这不起作用的原因是UIPreviewGetureRecognizer
,它是UILongPressGestureRecognizer
的子类,但该子类失败。因此我认为与其使用isKindOfClass
,不如使用isMemberOfClass
不检查子类。
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
}
}