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

时间:2009-03-05 20:08:23

标签: iphone uitextview

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

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

7 个答案:

答案 0 :(得分:14)

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

答案 1 :(得分:11)

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

Heres sameple code(在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

答案 2 :(得分:7)

更好的解决方案 (无需调整任何内容或使用任何私有API:D)

如下所述,向textview添加新的UITapGestureRecognizers没有预期的结果,从不调用处理程序方法。这是因为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,其中每一个都有targetactiontarget不是UITextView它本身就是前向类UITextInteractionAssistant的一个对象。 (此助手是@package的{​​{1}} ivar,但是前向定义位于公共标题中:UITextField.h。

UITextView识别点击并在UITextTapRecognizer上调用oneFingerTap:,因此我们想拦截该调用:)

UITextInteractionAssistant

答案 3 :(得分:2)

您需要分配UITextView instance.delegate = self(假设您要处理同一控制器中的事件)

确保在界面中实现UITextViewDelegate协议...例如:

@interface myController : UIViewController <UITextViewDelegate>{
}

然后您可以实施以下任何一项


- (BOOL)textViewShouldBeginEditing:(UITextView *)textView;
- (BOOL)textViewShouldEndEditing:(UITextView *)textView;

- (void)textViewDidBeginEditing:(UITextView *)textView;
- (void)textViewDidEndEditing:(UITextView *)textView;

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text;
- (void)textViewDidChange:(UITextView *)textView;

- (void)textViewDidChangeSelection:(UITextView *)textView;

答案 4 :(得分:1)

我正在使用textview作为更大视图的子视图。我需要用户能够滚动textview,但不能编辑它。我想检测textview的superview上的单击,包括textview本身。

当然,我遇到了一个问题,即textview吞噬了它上面的触摸。禁用用户交互会解决此问题,但用户将无法滚动文本视图。

我的解决方案是使textview可编辑,并使用textview的shouldBeginEditing委托方法来检测textview中的点击。我只是返回NO,从而阻止编辑,但现在我知道已经点击了textview(以及superview)。在这个方法和superview的touchesEnded方法之间我有我需要的东西。

我知道这对那些想要访问实际触摸的用户不起作用,但是如果你想要做的只是检测一个水龙头,这种方法有效!

答案 5 :(得分:0)

如何制作UIScrollView和[scrollView addSubview: textview],以便滚动textview?

答案 6 :(得分:0)

您还可以发送Touch Down个活动。通过Interface Builder连接此事件。

enter image description here

然后在事件处理程序中添加代码

- (IBAction)onAppIDTap:(id)sender {
    //Your code
}