2013-02-06 11 views
5

Mam UITextView, które wyświetlają akapit. Na przykład:Obsługa zdarzeń dotykowych UITextView po dotknięciu słowa w nim

self.myTextView.text = @"This is a sample paragraph" 

Co chcę zrobić teraz to kiedy dotykam się słowo w niniejszym ustępie, takie jak „To”, funkcja będzie zadzwonić: [self aFunction:@"This"]

Czy są jakieś pomysły na obsługę to zdarzenie i sposób uzyskania parametru, którym jest dotknięte słowo użytkownika. Być może potrzebuję innego sposobu wyświetlania akapitu, a nie przez UITextView.

+0

U musiałby zrobić to słowo hiperłącze .... – IronManGill

+0

@ Gill-TheIronMan: potem trzeba zrobić cały tekst jako hiperłącza również nie jest możliwe w tej sytuacji. –

+0

Ładne pytanie, czekam też na rozwiązanie :) –

Odpowiedz

1

W poniższym przykładzie wykorzystania (UITextView)

Stworzyłem prostą UILabel podklasę, która pozwala mi ustawić wartość wstawka:

#import "WWLabel.h" 

#define WWLabelDefaultInset 5 

@implementation WWLabel 

@synthesize topInset, leftInset, bottomInset, rightInset; 

- (id)initWithFrame:(CGRect)frame 
{ 
    self = [super initWithFrame:frame]; 
    if (self) { 
     self.topInset = WWLabelDefaultInset; 
     self.bottomInset = WWLabelDefaultInset; 
     self.rightInset = WWLabelDefaultInset; 
     self.leftInset = WWLabelDefaultInset; 
    } 
    return self; 
} 

- (void)drawTextInRect:(CGRect)rect 
{ 
    UIEdgeInsets insets = {self.topInset, self.leftInset, 
     self.bottomInset, self.rightInset}; 

    return [super drawTextInRect:UIEdgeInsetsInsetRect(rect, insets)]; 
} 

Potem stworzył podklasy UIView, który zawierał moje niestandardową etykietę i po dotknięciu skonstruował rozmiar tekstu dla każdego słowa w etykiecie, aż rozmiar przekroczył wartość lokalizacji dotknięcia - jest to słowo, które zostało dotknięte. To nie jest perfekcyjne, ale na razie działa wystarczająco dobrze.

I następnie wykorzystywane prosty NSAttributedString aby podświetlić tekst:

#import "WWPhoneticTextView.h" 
#import "WWLabel.h" 

#define WWPhoneticTextViewInset 5 
#define WWPhoneticTextViewDefaultColor [UIColor blackColor] 
#define WWPhoneticTextViewHighlightColor [UIColor yellowColor] 

#define UILabelMagicTopMargin 5 
#define UILabelMagicLeftMargin -5 

@implementation WWPhoneticTextView { 
    WWLabel *label; 
    NSMutableAttributedString *labelText; 
    NSRange tappedRange; 
} 

// ... skipped init methods, very simple, just call through to configureView 

- (void)configureView 
{ 
    if(!label) { 
     tappedRange.location = NSNotFound; 
     tappedRange.length = 0; 

     label = [[WWLabel alloc] initWithFrame:[self bounds]]; 
     [label setLineBreakMode:NSLineBreakByWordWrapping]; 
     [label setNumberOfLines:0]; 
     [label setBackgroundColor:[UIColor clearColor]]; 
     [label setTopInset:WWPhoneticTextViewInset]; 
     [label setLeftInset:WWPhoneticTextViewInset]; 
     [label setBottomInset:WWPhoneticTextViewInset]; 
     [label setRightInset:WWPhoneticTextViewInset]; 

     [self addSubview:label]; 
    } 


    // Setup tap handling 
    UITapGestureRecognizer *singleFingerTap = [[UITapGestureRecognizer alloc] 
               initWithTarget:self action:@selector(handleSingleTap:)]; 
    singleFingerTap.numberOfTapsRequired = 1; 
    [self addGestureRecognizer:singleFingerTap]; 
} 

- (void)setText:(NSString *)text 
{ 
    labelText = [[NSMutableAttributedString alloc] initWithString:text]; 
    [label setAttributedText:labelText]; 
} 

- (void)handleSingleTap:(UITapGestureRecognizer *)sender 
{ 
    if (sender.state == UIGestureRecognizerStateEnded) 
    { 
     // Get the location of the tap, and normalise for the text view (no margins) 
     CGPoint tapPoint = [sender locationInView:sender.view]; 
     tapPoint.x = tapPoint.x - WWPhoneticTextViewInset - UILabelMagicLeftMargin; 
     tapPoint.y = tapPoint.y - WWPhoneticTextViewInset - UILabelMagicTopMargin; 

     // Iterate over each word, and check if the word contains the tap point in the correct line 
     __block NSString *partialString = @""; 
     __block NSString *lineString = @""; 
     __block int currentLineHeight = label.font.pointSize; 
     [label.text enumerateSubstringsInRange:NSMakeRange(0, [label.text length]) options:NSStringEnumerationByWords usingBlock:^(NSString* word, NSRange wordRange, NSRange enclosingRange, BOOL* stop){ 

      CGSize sizeForText = CGSizeMake(label.frame.size.width-2*WWPhoneticTextViewInset, label.frame.size.height-2*WWPhoneticTextViewInset); 
      partialString = [NSString stringWithFormat:@"%@ %@", partialString, word]; 

      // Find the size of the partial string, and stop if we've hit the word 
      CGSize partialStringSize = [partialString sizeWithFont:label.font constrainedToSize:sizeForText lineBreakMode:label.lineBreakMode]; 

      if (partialStringSize.height > currentLineHeight) { 
       // Text wrapped to new line 
       currentLineHeight = partialStringSize.height; 
       lineString = @""; 
      } 
      lineString = [NSString stringWithFormat:@"%@ %@", lineString, word]; 

      CGSize lineStringSize = [lineString sizeWithFont:label.font constrainedToSize:label.frame.size lineBreakMode:label.lineBreakMode]; 
      lineStringSize.width = lineStringSize.width + WWPhoneticTextViewInset; 

      if (tapPoint.x < lineStringSize.width && tapPoint.y > (partialStringSize.height-label.font.pointSize) && tapPoint.y < partialStringSize.height) { 
       NSLog(@"Tapped word %@", word); 
       if (tappedRange.location != NSNotFound) { 
        [labelText addAttribute:NSForegroundColorAttributeName value:[UIColor blackColor] range:tappedRange]; 
       } 

       tappedRange = wordRange; 
       [labelText addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:tappedRange]; 
       [label setAttributedText:labelText]; 
       *stop = YES; 
      } 
     }];   
    } 
} 
+0

Dziękuję bardzo! Spróbuję tego. – hnimnart

+0

Widziałem Twoją drogę, ale nie udało mi się jej zrealizować, a teraz znalazłem błąd. – hnimnart

Powiązane problemy