24

iPhone の UITextView でタッチを処理しようとしています。たとえば、UIImageViewsのサブクラスを作成し、touchesBeganメソッドを実装することで、タップやその他のタッチイベントを正常に処理できました...ただし、明らかにUITextViewでは機能しません:(

UITextView には、ユーザー インタラクションとマルチ タッチが有効になっています。誰でもこれを処理できましたか?

4

7 に答える 7

11

UITextView でシングル/ダブル/トリプル タップを処理する場合は、UIGestureReconnizer を委譲し、textview にジェスチャ レコグナイザーを追加できます。

Heres の同じコード (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

于 2011-08-11T05:02:49.880 に答える
7

より良い解決策 (何かをスウィズルしたり、プライベートAPIを使用したりせずに:D)

以下で説明するようUITapGestureRecognizersに、textview に new を追加しても期待どおりの結果が得られず、ハンドラー メソッドが呼び出されることはありません。これは、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 ...
}

このようにすることで、テキストビューがいつジェスチャー認識エンジンを変更しても、必要なタップジェスチャー認識エンジンを常にキャッチします→したがって、ハンドラーメソッドはそれに応じて呼び出されます:)

結論: にジェスチャ レコグナイザーを追加する場合UITextViewは、テキスト ビューにジェスチャ レコグナイザーがまだ含まれていないことを確認する必要があります。

  • それがない場合は、通常の方法で行ってください。(ジェスチャ レコグナイザーを作成し、セットアップして、テキスト ビューに追加します) これで完了です!
  • ある場合、おそらく上記と同様のことを行う必要があります。



古い回答

以前の回答には短所があり、期待どおりに機能しないため、プライベートメソッドをスウィズルしてこの回答を思いつきました。ここでは、 のタッピング動作を変更するのではなくUITextView、呼び出されたメソッドをインターセプトして、元のメソッドを呼び出すだけです。

詳細説明

UITextViewUIGestureRecognizersこれらにはそれぞれ atargetと aactionがありますが、それらtargetはそれ自体ではなく、 forwardUITextViewクラスのオブジェクトですUITextInteractionAssistant。(このアシスタントはの@packageivar ですUITextViewが、前方定義はパブリック ヘッダー: UITextField.h にあります)。

UITextTapRecognizerのタップと通話oneFingerTap:を認識するUITextInteractionAssistantので、その通話を傍受したい :)

#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));
}
于 2011-11-21T12:40:47.143 に答える
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;

于 2009-03-06T05:37:38.693 に答える
1

大きなビューのサブビューとしてテキストビューを使用しています。ユーザーがテキストビューをスクロールできるようにする必要がありますが、編集することはできません。テキストビュー自体を含め、テキストビューのスーパービューのシングルタップを検出したいと思います。

もちろん、私はテキストビューがそれから始まるタッチを飲み込むという問題に遭遇しました。ユーザーインタラクションを無効にするとこれは修正されますが、ユーザーはテキストビューをスクロールできなくなります。

私の解決策は、テキストビューを編集可能にし、テキストビューのshouldBeginEditingデリゲートメソッドを使用してテキストビューのタップを検出することでした。NOを返すだけで編集できなくなりますが、テキストビュー(したがってスーパービュー)がタップされていることがわかります。このメソッドとsuperviewのtouchesEndedメソッドの間に必要なものがあります。

これは実際のタッチにアクセスしたい人には機能しないことを私は知っていますが、タップを検出するだけであれば、このアプローチは機能します!

于 2010-08-25T21:18:40.833 に答える
0

Touch Downイベントを送信することもできます。Interface Builder を介してこのイベントを関連付けます。

ここに画像の説明を入力

次に、イベント ハンドラーにコードを追加します。

- (IBAction)onAppIDTap:(id)sender {
    //Your code
}
于 2014-07-08T00:26:12.063 に答える
0

UIScrollView を作成して、[scrollView addSubview: textview]テキストビューをスクロールできるようにするのはどうですか?

于 2011-11-25T21:57:54.383 に答える