首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >(iPhone)如何处理UITextView上的触摸?

(iPhone)如何处理UITextView上的触摸?
EN

Stack Overflow用户
提问于 2009-03-05 20:08:23
回答 7查看 30.1K关注 0票数 24

我正在试着处理iPhone的UITextView上的触碰。我成功地处理了点击和其他触摸事件,例如,创建了UIImageViews的一个子类,并实现了显然不能与UITextView一起工作的touchesBegan method...however :(

UITextView有用户交互和多点触控功能,只是为了sure...no没有joy。有人想办法解决这个问题吗?

EN

回答 7

Stack Overflow用户

发布于 2009-05-08 16:38:33

UITextView (UIScrollView的子类)包含了大量的事件处理。它处理复制和粘贴以及数据检测器。也就是说,这可能是一个bug,它不会传递未处理的事件。

有一个简单的解决方案:你可以子类化UITextView并在你自己的版本中嵌入你自己的touchesEnded (和其他事件处理消息),你应该在每个触摸处理方法中调用[super touchesBegan:touches withEvent:event];

代码语言:javascript
复制
#import "MyTextView.h"  //MyTextView:UITextView
@implementation MyTextView

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    NSLog(@"touchesBegan");
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
        [super touchesBegan:touches withEvent:event];
    NSLog(@"touchesMoved");
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
    NSLog(@"****touchesEnded");
    [self.nextResponder touchesEnded: touches withEvent:event]; 
    NSLog(@"****touchesEnded");
    [super touchesEnded:touches withEvent:event];
    NSLog(@"****touchesEnded");
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event{
[super touches... etc]; 
NSLog(@"touchesCancelled");
}
票数 14
EN

Stack Overflow用户

发布于 2011-08-11 13:02:50

如果你想在UITextView上处理单击/双击/三次点击,你可以委托UIGestureRecongnizer并在你的文本视图上添加手势识别器。

以下是示例代码(在viewDidLoad中):

代码语言:javascript
复制
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap)];

//modify this number to recognizer number of tap
[singleTap setNumberOfTapsRequired:1];
[self.textView addGestureRecognizer:singleTap];
[singleTap release];

代码语言:javascript
复制
-(void)handleSingleTap{
   //handle tap in here 
   NSLog(@"Single tap on view");
}

希望这能有所帮助:D

票数 11
EN

Stack Overflow用户

发布于 2011-11-21 20:40:47

更好的解决方案(不使用任何东西或使用任何私有API :D )

如下所述,向文本视图添加新的UITapGestureRecognizers不会有预期的结果,处理程序方法永远不会被调用。这是因为UITextView已经设置了一些点击手势识别器,我认为他们的代理不允许我的手势识别器正常工作,我相信更改他们的代理可能会导致更糟糕的结果。

幸运的是,UITextView已经设置了我想要的手势识别器,问题是它会根据视图的状态而变化(即:输入日语时的手势识别器集与输入英语时的手势识别器集不同,也不在编辑模式下)。我通过在UITextView的一个子类中覆盖它们来解决这个问题:

代码语言:javascript
复制
- (void)addGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
{
    [super addGestureRecognizer:gestureRecognizer];
    // Check the new gesture recognizer is the same kind as the one we want to implement
    // Note:
    // This works because `UITextTapRecognizer` is a subclass of `UITapGestureRecognizer`
    // and the text view has some `UITextTapRecognizer` added :)
    if ([gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]) {
        UITapGestureRecognizer *tgr = (UITapGestureRecognizer *)gestureRecognizer;
        if ([tgr numberOfTapsRequired] == 1 &&
            [tgr numberOfTouchesRequired] == 1) {
            // If found then add self to its targets/actions
            [tgr addTarget:self action:@selector(_handleOneFingerTap:)];
        }
    }
}
- (void)removeGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
{
    // Check the new gesture recognizer is the same kind as the one we want to implement
    // Read above note
    if ([gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]) {
        UITapGestureRecognizer *tgr = (UITapGestureRecognizer *)gestureRecognizer;
        if ([tgr numberOfTapsRequired] == 1 &&
            [tgr numberOfTouchesRequired] == 1) {
            // If found then remove self from its targets/actions
            [tgr removeTarget:self action:@selector(_handleOneFingerTap:)];
        }
    }
    [super removeGestureRecognizer:gestureRecognizer];
}

- (void)_handleOneFingerTap:(UITapGestureRecognizer *)tgr
{
    NSDictionary *userInfo = [NSDictionary dictionaryWithObject:tgr forKey:@"UITapGestureRecognizer"];
    [[NSNotificationCenter defaultCenter] postNotificationName:@"TextViewOneFingerTapNotification" object:self userInfo:userInfo];
    // Or I could have handled the action here directly ...
}

通过这样做,无论文本视图何时更改其手势识别器,我们都将始终捕获我们想要的点击手势识别器。因此,我们的→方法将被相应地调用:)

结论:如果你想在UITextView中添加一个手势识别器,你必须检查文本视图是否已经有了它。

  • 如果没有,只需按常规方式操作即可。(创建您的手势识别器,设置它,并将其添加到文本视图中),就完成了!.
  • 如果它有它,那么您可能需要执行类似于上面的操作。

旧答案

我是通过使用私有方法的得到这个答案的,因为之前的答案有缺点,它们不能像预期的那样工作。在这里,我只是截取被调用的方法,然后调用原始方法,而不是修改UITextView的点击行为。

进一步解释

UITextView有一堆专门的UIGestureRecognizers,每个都有一个target和一个action,但是它们的target不是UITextView本身,它是forward类UITextInteractionAssistant的一个对象。(此助手是UITextView@package ivar,但转发定义在公共标头中: UITextField.h)。

UITextTapRecognizer识别taps并调用UITextInteractionAssistant上的oneFingerTap:,因此我们希望拦截该调用:)

代码语言:javascript
复制
#import <objc/runtime.h>

// Prototype and declaration of method that is going be swizzled
// When called: self and sender are supposed to be UITextInteractionAssistant and UITextTapRecognizer objects respectively
void proxy_oneFingerTap(id self, SEL _cmd, id sender);
void proxy_oneFingerTap(id self, SEL _cmd, id sender){ 
    [[NSNotificationCenter defaultCenter] postNotificationName:@"TextViewOneFinderTap" object:self userInfo:nil];
    if ([self respondsToSelector:@selector(proxy_oneFingerTap:)]) {
        [self performSelector:@selector(proxy_oneFingerTap:) withObject:sender];
    }
}

...
// subclass of UITextView
// Add above method and swizzle it with.
- (void)doTrickForCatchingTaps
{
    Class class = [UITextInteractionAssistant class]; // or below line to avoid ugly warnings
    //Class class = NSClassFromString(@"UITextInteractionAssistant");
    SEL new_selector = @selector(proxy_oneFingerTap:);
    SEL orig_selector = @selector(oneFingerTap:);

    // Add method dynamically because UITextInteractionAssistant is a private class
    BOOL success = class_addMethod(class, new_selector, (IMP)proxy_oneFingerTap, "v@:@");
    if (success) {
        Method originalMethod = class_getInstanceMethod(class, orig_selector);
        Method newMethod = class_getInstanceMethod(class, new_selector);
        if ((originalMethod != nil) && (newMethod != nil)){
            method_exchangeImplementations(originalMethod, newMethod); // Method swizzle
        }
    }
}

//... And in the UIViewController, let's say

[textView doTrickForCatchingTaps];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textViewWasTapped:) name:@"TextViewOneFinderTap" object:nil];

- (void)textViewWasTapped:(NSNotification *)noti{
    NSLog(@"%@", NSStringFromSelector:@selector(_cmd));
}
票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/616411

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档