UILabel коснитесь и получите текст, где коснулся - PullRequest
6 голосов
/ 07 декабря 2010

У меня есть UILabel, у которого есть несколько текстовых и двухмесячных названий, таких как «В январе и июле солнце будет пиковым», я подклассифицировал UILabel и добавил к нему событие касания.Теперь я хочу получить слово под текстом, к которому прикоснулся пользователь, и узнать, коснулся ли пользователь января / июля или нет.Возможно ли это?

Ответы [ 5 ]

3 голосов
/ 07 декабря 2010

Я думаю, вы найдете то, что ищете в документации для UITextInputProtocol .

Для получения более подробной информации обратитесь к руководству Apple по Text, Web и редактированию , в частности, в разделе «Экскурсия по реализации UITextInput». В нем обсуждается, как вы можете создавать индексированные позиции в тексте, и спрашивает, какие текстовые позиции они получили ближе всего.

Apple ссылается на пример проекции под названием SimpleTextInput, но я не могу его найти. Я буду продолжать искать.

1 голос
/ 11 сентября 2013

Я реализовал ваш вопрос, просто для удовольствия на моем блоге .

Просто я вложил в подкласс UILabel, добавив touchEnded, для распознавания положения касания и положения буквы.

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
  UITouch *touch = [[touches allObjects] objectAtIndex:0];
  CGPoint pos    = [touch locationInView:self];

  int sizes[self.text.length];
  for ( int i=0; i<self.text.length; i++ )
  {
    char letter         = [self.text characterAtIndex:i];
    NSString *letterStr = [NSString stringWithFormat:@"%c", letter];

    CGSize letterSize   = [letterStr sizeWithFont:self.font];
    sizes[i]            = letterSize.width;
  }

  int sum = 0;
  for ( int i=0; i<self.text.length; i++)
  {
    sum += sizes[i];
    if ( sum >= pos.x )
    {
      [ _delegate didLetterFound:[ self.text characterAtIndex:i] ];
      return;
    }
  }
}

Надеюсь, это поможет
веселит.

0 голосов
/ 15 апреля 2015
 
- (void)tapped:(UITapGestureRecognizer *)tap
{
    CGPoint location = [tap locationInView:_label];

    NSDictionary *attribute = @{NSFontAttributeName: _label.font};
    CGFloat width = 0;
    for (int i = 0; i substringWithRange:NSMakeRange(i, 1)];
        CGSize lettersize = [letterStr sizeWithAttributes:attribute];
        width += lettersize.width;
        if (width >= location.x ) {
            NSLog(@"str: %@", letterStr);
            break;
        }
    }
}
0 голосов
/ 12 июля 2014

У меня была такая же проблема, как у оригинального постера.Я хотел, чтобы пользователь мог долго нажимать на UILabel, которая отображала список строк, разделенных запятыми, и извлекать подстроку, соответствующую месту касания между ближайшими запятыми.

Проблемав том, что UILabel не реализует протокол UITextInput, в противном случае реализация будет простой.

Мне не понравились какие-либо из предложенных обходных путей, которые я нашел, поэтому я решил найти собственное решение.После некоторых размышлений и исследований я понял, что, хотя UILabel не поддерживает UITextInput, UITextView поддерживает.Я не хотел заменять все UILabels в пользовательском интерфейсе на UITextViews, поэтому я подумал: «Почему бы программно не создать UITextView за кулисами с точно такими же настройками рендеринга текста и использовать его методы UITextInput для сопоставления точки касания сжелаемая подстрока?

Это оказалось идеальным решением с моей точки зрения.

Я подключил UILongPressGestureRecognizer к UILabels и вызвал следующую функцию в обработчике жестов:

-(NSString*)commaDelineatedTextAtTouchPosition:(UILongPressGestureRecognizer*)longPress
{
    UILabel *gestureRecipient = (UILabel*)longPress.view;
    UITextView *textRegionClone = [[UITextView alloc] initWithFrame:gestureRecipient.frame];

    // tweak the text view's content area to get the same rendering (placement and wrapping)
    textRegionClone.textContainerInset = UIEdgeInsetsMake(0.0, -5.0, 0.0, -5.0);
    // copy the label's text properties
    textRegionClone.text = gestureRecipient.text;
    textRegionClone.font = gestureRecipient.font;
    [textRegionClone setNeedsDisplay];
    CGPoint loc = [longPress locationInView:gestureRecipient];
    UITextPosition *charR = [textRegionClone closestPositionToPoint:loc];

    id<UITextInputTokenizer> tokenizer = textRegionClone.tokenizer;
    UITextRange *searchRange = [tokenizer rangeEnclosingPosition:charR withGranularity:UITextGranularityCharacter inDirection:UITextStorageDirectionBackward];
    NSString *commaEnclosedText = @"";

    if (searchRange != nil) {
        NSString *tapChar = [textRegionClone textInRange:searchRange];

        if ([tapChar isEqualToString:@","]) { // tapped right on a ","
            // move the end of the range to immediately before the ","
            searchRange = [textRegionClone textRangeFromPosition:searchRange.start toPosition:[textRegionClone positionFromPosition:searchRange.end offset:-1]];
        }

        UITextPosition *docStart = textRegionClone.beginningOfDocument;

        // search back to find the leading comma or the beginning of the text
        do {
            searchRange = [textRegionClone textRangeFromPosition:[textRegionClone positionFromPosition:searchRange.start offset:-1] toPosition:searchRange.end];
            commaEnclosedText = [textRegionClone textInRange:searchRange];
        }
        while (([searchRange.start isEqual:docStart] == NO) && ([commaEnclosedText characterAtIndex:0] != ','));

        // now search forward to the trailing comma or the end of the text
        UITextPosition *docEnd = textRegionClone.endOfDocument;

        while (([searchRange.end isEqual:docEnd] == NO) && ([commaEnclosedText characterAtIndex:commaEnclosedText.length - 1] != ',')) {
            searchRange = [textRegionClone textRangeFromPosition:searchRange.start toPosition:[textRegionClone positionFromPosition:searchRange.end offset:1]];
            commaEnclosedText = [textRegionClone textInRange:searchRange];
        }

        commaEnclosedText = [[commaEnclosedText stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@","]] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    }

    return commaEnclosedText;
}

Единственное, что немного огорчает эту технику, это то, что вам нужно вручную настроить рендеринг в UITextView, отрегулировав область textContainerInset.В противном случае вы не получите точно такую ​​же упаковку и размещение текста в UITextView, как в UILabel.В противном случае это достаточно общий код, который должен работать для всех остальных.

0 голосов
/ 11 сентября 2013

Я решил эту проблему, поместив прозрачные UIViews поверх UILabel, которые были подключены для обработки сенсорных событий. Вы можете настроить положение и размер меток зоны попадания, рассчитав размер соответствующих частей текста. Этот подход также имеет преимущество в том, что он позволяет настраивать размеры зон попадания, чтобы сделать их больше и легче касаться толстыми пальцами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...