Ios 模拟UITextView的默认双击行为

Ios 模拟UITextView的默认双击行为,ios,xcode,uitextview,uigesturerecognizer,uitapgesturerecognizer,Ios,Xcode,Uitextview,Uigesturerecognizer,Uitapgesturerecognizer,有人知道当用户在UITextView中用两个手指轻触时调用什么方法吗 当用户用两个手指轻敲时,段落中的整个文本被选中。我希望以编程方式实现相同的选择,以使此段落选择在我的自定义单点击手势方法中可用 从UITextView双击手势识别器的默认行为判断,我认为selectAll:是被调用来处理文本选择的方法。类似地,您可以使用注释中所述的现有TapTextView手势:方法中的selectAll:强制文本视图在识别单点击手势识别器时选择文本 如果您希望文本选项自动显示,就像它们响应默认的双击手势识别

有人知道当用户在UITextView中用两个手指轻触时调用什么方法吗

当用户用两个手指轻敲时,段落中的整个文本被选中。我希望以编程方式实现相同的选择,以使此段落选择在我的自定义单点击手势方法中可用

从UITextView双击手势识别器的默认行为判断,我认为selectAll:是被调用来处理文本选择的方法。类似地,您可以使用注释中所述的现有TapTextView手势:方法中的selectAll:强制文本视图在识别单点击手势识别器时选择文本

如果您希望文本选项自动显示,就像它们响应默认的双击手势识别器(即剪切、复制、粘贴等)一样,请将selectAll:设置为self:

否则,要仅选择文本而不显示菜单,请将其设置为零:

更新

正如OP在评论中指出的,UITextView双击手势识别器最初只会选择一个段落

首先,从当前光标位置显示编辑菜单:

// Access the application's shared menu
UIMenuController *menu = [UIMenuController sharedMenuController];

// Calculate the cursor's position within the superview
// and convert it to a CGRect
CGPoint cursorPosition = [self.textView caretRectForPosition:self.textView.selectedTextRange.start].origin;
CGPoint cursorPositionInView = [self.textView convertPoint:cursorPosition toView:self.view];
CGRect menuRect = CGRectMake(cursorPositionInView.x, cursorPositionInView.y, 0, 0);

// Show the menu from the cursor's position
[menu setTargetRect:menuRect inView:self.view];
[menu setMenuVisible:YES animated:YES];
然后选择当前段落,我推荐如下:

// Break the text into components separated by the newline character
NSArray *paragraphs = [self.textView.text componentsSeparatedByString:@"\n"];

// Keep a tally of the paragraph character count
int characterCount = 0;

// Go through each paragraph
for (NSString *paragraph in paragraphs) {

    // If the total number of characters up to the end
    // of the current paragraph is greater than or
    // equal to the start of the textView's selected
    // range, select the most recent paragraph and break
    // from the loop
    if (characterCount + paragraph.length >= self.textView.selectedRange.location) {
        [self.textView setSelectedRange:NSMakeRange(characterCount, paragraph.length)];
        break;
    }

    // Increment the character count by adding the current
    // paragraph length + 1 to account for the newline character
    characterCount += paragraph.length + 1;
}
参见协议参考:

采用UITokenizer协议的类的实例是标记器;标记器允许文本输入系统评估不同粒度的文本单位。文本单位的粒度始终参照存储或参照方向进行评估

根据协议,使用-uitextange*rangeEnclosuringPosition:UITextPosition*position with granularity:uitextGranularityIndirection:UITextDirectiondirection并将UITextGranularity设置为UITextGranularityParagraph,以检测具有已设置粒度的文本范围

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{

  if (touches.count == 2) {
    UITouch *touch = [[event allTouches] anyObject];
    CGPoint touchLocation = [touch locationInView:self.textView];

    //calculate the distance from touch
    UITextPosition *position = [self.textView closestPositionToPoint:touchLocation];
    NSUInteger distanceFromTouch = [self.textView offsetFromPosition:self.textView.beginningOfDocument
                                                          toPosition:position];
    //calculate the position by offset 
    UITextPosition *positionOffset = [self.textView positionFromPosition:self.textView.beginningOfDocument
                                                  offset:distanceFromTouch];

    //set up the granularity
    UITextGranularity granularity = UITextGranularityParagraph;

    //implement the protocol
    id<UITextInputTokenizer> tokenizer = self.textView.tokenizer;
    UITextRange *textRange = [tokenizer rangeEnclosingPosition:positionOffset
                                               withGranularity:granularity
                                                   inDirection:UITextWritingDirectionLeftToRight];

    //select the textRange
    [self.textView setSelectedTextRange:textRange];

    self.textView.keyboardType = UIKeyboardTypeNamePhonePad;

  }
}

别忘了分配协议@interface ViewController

您是否已经设置了自定义的单点击手势和相关方法?是,-IBActionTapTextView手势:idsender{NSLog@TAP}非常感谢,这种方法很有效,但不是用于选择单独的段落,而是选择UITextView中的所有文本。我的文本视图中的文本由几个段落组成。这些段落被\n\n空格分隔。在我的应用程序中,我只需要选择用户点击的段落,而不是TextView中的整个文本。难道你不知道如何实现段落选择吗?需要与Notes应用程序中相同的功能,但只需点击一下,以下是屏幕截图。您可以在这个屏幕截图上看到,当用户点击这个段落时,它只选择段落,而不是整个文本。谢谢Lyndsey。您的代码可以工作,但在我的例子中,共享菜单并不总是出现在段落的顶部。所以我把你的代码和@WorldOfWarcraft的代码混合在一起。@Adelmaer哦,我想我知道你的意思了……因为段落的顶部可能看不见,因此菜单将显示在文本视图的上方。。。我想最好是1在选择文本之前显示菜单,以便显示用户单击的位置,或者2滚动到段落的开头。。。现在,我将编辑选项1的答案。谢谢,这对于UITextView中的整个文本也很好,但对于段落则不行,我还添加了[self.textView becomeFirstResponder];要使其在my-iBactionTapTextView手势:idsender方法中工作。但是在我的例子中,我只需要选择用户触摸到的段落,而不是文本视图中的整个文本。如果在notes应用程序中双击某个段落,则只会选择该段落,而不会选择整个文本。我需要相同的功能。下面是一个例子:谢谢你,这台Uitokeniser真的很棒。但在我的应用程序中不显示点击复制。这就是为什么我最终将你的代码与粒度和Lyndsey关于显示复制菜单的答案中的代码混合在一起。@Adelmaer你是说剪切/复制/粘贴菜单,为什么我的设备会显示?我想这是我的错,因为我把你的代码放在了-iBactionTapTextViewSirter:idsender方法中,不在-voidtouchesEnded:NSSet*接触事件:UIEvent*事件方法。最后决定做一个自定义的编辑菜单,一切正常。再次感谢你,你的回答帮了大忙,也解决了问题。@Adelmaer:没问题。
// Break the text into components separated by the newline character
NSArray *paragraphs = [self.textView.text componentsSeparatedByString:@"\n"];

// Keep a tally of the paragraph character count
int characterCount = 0;

// Go through each paragraph
for (NSString *paragraph in paragraphs) {

    // If the total number of characters up to the end
    // of the current paragraph is greater than or
    // equal to the start of the textView's selected
    // range, select the most recent paragraph and break
    // from the loop
    if (characterCount + paragraph.length >= self.textView.selectedRange.location) {
        [self.textView setSelectedRange:NSMakeRange(characterCount, paragraph.length)];
        break;
    }

    // Increment the character count by adding the current
    // paragraph length + 1 to account for the newline character
    characterCount += paragraph.length + 1;
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{

  if (touches.count == 2) {
    UITouch *touch = [[event allTouches] anyObject];
    CGPoint touchLocation = [touch locationInView:self.textView];

    //calculate the distance from touch
    UITextPosition *position = [self.textView closestPositionToPoint:touchLocation];
    NSUInteger distanceFromTouch = [self.textView offsetFromPosition:self.textView.beginningOfDocument
                                                          toPosition:position];
    //calculate the position by offset 
    UITextPosition *positionOffset = [self.textView positionFromPosition:self.textView.beginningOfDocument
                                                  offset:distanceFromTouch];

    //set up the granularity
    UITextGranularity granularity = UITextGranularityParagraph;

    //implement the protocol
    id<UITextInputTokenizer> tokenizer = self.textView.tokenizer;
    UITextRange *textRange = [tokenizer rangeEnclosingPosition:positionOffset
                                               withGranularity:granularity
                                                   inDirection:UITextWritingDirectionLeftToRight];

    //select the textRange
    [self.textView setSelectedTextRange:textRange];

    self.textView.keyboardType = UIKeyboardTypeNamePhonePad;

  }
}