当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《(iPhone)如何处理UITextView上的触摸?》经验,为你挑选了3个好方法。

我正试图处理iPhone的UITextView上的触摸.我成功设法通过创建UIImageViews的子类来处理点击和其他触摸事件,并实现touchesBegan方法...但是这显然不适用于UITextView :(

UITextView具有用户交互和多点触控功能,只是为了确保......不会没有快乐.有人设法处理这个?



1> 小智..:

UITextView(UIScrollView的子类)包含许多事件处理.它处理复制和粘贴以及数据检测器.也就是说,它可能是一个错误,它没有传递未处理的事件.

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

#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");
}


这对我来说仍然很奇怪.你为什么要在touchesMoved上调用touchesBegan super?这不是意味着你会一遍又一遍地调用touchesBegan而且touchesMoved永远不会被super处理吗?

2> REALFREE ..:

如果要在UITextView上处理单/双/三击,可以委托UIGestureRecongnizer并在textview上添加手势识别器.

Heres sameple代码(在viewDidLoad中):

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];

-(void)handleSingleTap{
   //handle tap in here 
   NSLog(@"Single tap on view");
}

希望这有帮助:D



3> nacho4d..:

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

如下所述,向UITapGestureRecognizerstextview 添加新内容没有预期的结果,从不调用处理程序方法.这是因为UITextView已经有一些轻敲手势识别器设置,我认为他们的代表不允许我的手势识别器正常工作,更改他们的代表可能会导致更糟糕的结果,我相信.

幸运的是,UITextView我想要设置的手势识别器,问题在于它根据视图的状态而改变(即:输入日语时的手势识别器组与输入英语时不同,并且当不处于编辑模式时).我通过在UITextView的子类中重写这些来解决这个问题:

- (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 ...
}

通过这种方式,无论textview何时更改其手势识别器,我们将始终捕获我们想要的轻敲手势识别器→因此,我们的处理程序方法将相应地调用:)

结论: 如果要添加手势识别器,则UITextView必须检查文本视图是否已经存在.

如果它没有它,只需按常规方式进行.(创建手势识别器,进行设置,然后将其添加到文本视图中),您就完成了!

如果确实有,那么你可能需要做类似的事情.




老答案

我通过调整私有方法得出了这个答案,因为以前的答案有缺点,并且它们没有按预期工作.在这里,UITextView我只是拦截被调用的方法然后调用原始方法,而不是修改其攻击行为.

进一步说明

UITextView有一堆专门的UIGestureRecognizers,每一个都有一个target和一个,action但它们target不是它UITextView自己,它是前进阶级的一个对象UITextInteractionAssistant.(这个助手是一个@packageivar UITextView但是正向定义在公共标题中:UITextField.h).

UITextTapRecognizer识别点击和调用oneFingerTap:,UITextInteractionAssistant所以我们想拦截那个调用:)

#import 

// 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));
}

推荐阅读
夏晶阳--艺术
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有