From 45a608f07d66c70fd0d7296e7732215fdd606fb8 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Sun, 8 Feb 2015 16:12:29 -0800 Subject: [PATCH] Added a property "linkCornerRadius" to allow rounded rect Draw a rounded rect around link text when tapped, similar to the original iOS design. --- .../CCHLinkTextView Example/ViewController.m | 4 ++- CCHLinkTextView/CCHLinkTextView.h | 3 ++ CCHLinkTextView/CCHLinkTextView.m | 36 +++++++++++++++++++ README.md | 2 ++ 4 files changed, 44 insertions(+), 1 deletion(-) diff --git a/CCHLinkTextView Example/CCHLinkTextView Example/ViewController.m b/CCHLinkTextView Example/CCHLinkTextView Example/ViewController.m index 46a042c..a3449f4 100644 --- a/CCHLinkTextView Example/CCHLinkTextView Example/ViewController.m +++ b/CCHLinkTextView Example/CCHLinkTextView Example/ViewController.m @@ -85,7 +85,9 @@ [self.longPressGestureRecognizer requireGestureRecognizerToFail:linkTextView.linkGestureRecognizer]; linkTextView.linkDelegate = self; linkTextView.linkTextAttributes = @{NSForegroundColorAttributeName : [UIColor blueColor]}; - linkTextView.linkTextTouchAttributes = @{NSForegroundColorAttributeName : [UIColor orangeColor]}; + linkTextView.linkTextTouchAttributes = @{NSForegroundColorAttributeName : [UIColor orangeColor], + NSBackgroundColorAttributeName: [UIColor darkGrayColor]}; + linkTextView.linkCornerRadius = 4.0f; } - (void)linkTextView:(CCHLinkTextView *)linkTextView didTapLinkWithValue:(id)value diff --git a/CCHLinkTextView/CCHLinkTextView.h b/CCHLinkTextView/CCHLinkTextView.h index fcd87ab..7efccc2 100644 --- a/CCHLinkTextView/CCHLinkTextView.h +++ b/CCHLinkTextView/CCHLinkTextView.h @@ -53,6 +53,9 @@ extern NSString *const CCHLinkAttributeName; /** The gesture recognizer used to detect links in this text view. */ @property (nonatomic, readonly) CCHLinkGestureRecognizer *linkGestureRecognizer; +/** The corner radius of the rounded rectangle that is shown when link touched. (default = 0 point) */ +@property (nonatomic) CGFloat linkCornerRadius; + /** For the given ranges, enumerates all view rectangles that cover each range. @param ranges array of ranges. diff --git a/CCHLinkTextView/CCHLinkTextView.m b/CCHLinkTextView/CCHLinkTextView.m index 584ae6e..7c7be8a 100644 --- a/CCHLinkTextView/CCHLinkTextView.m +++ b/CCHLinkTextView/CCHLinkTextView.m @@ -200,6 +200,36 @@ NSString *const CCHLinkAttributeName = @"CCHLinkAttributeName"; return linkFound; } +- (void)drawRoundedCornerForRange:(NSRange)range +{ + CALayer * layer = [[CALayer alloc] init]; + layer.frame = self.bounds; + layer.backgroundColor = [[UIColor clearColor] CGColor]; + + UIGraphicsBeginImageContextWithOptions(layer.bounds.size, NO, 0.0); + CGContextRef context = UIGraphicsGetCurrentContext(); + CGContextSetFillColorWithColor(context, [[UIColor whiteColor] CGColor]); + CGContextFillRect(context, layer.bounds); // Unmask the whole text area + + NSRange glyphRange = [self.layoutManager glyphRangeForCharacterRange:range actualCharacterRange:NULL]; + [self.layoutManager enumerateEnclosingRectsForGlyphRange:glyphRange withinSelectedGlyphRange:NSMakeRange(NSNotFound, 0) inTextContainer:self.textContainer usingBlock:^(CGRect rect, BOOL *stop) { + rect.origin.x += self.textContainerInset.left; + rect.origin.y += self.textContainerInset.top; + + CGContextClearRect(context, CGRectInset(rect, -1, -1)); // Mask the rectangle of the range + + CGContextAddPath(context, [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:self.linkCornerRadius].CGPath); + CGContextSetFillColorWithColor(context, [[UIColor whiteColor] CGColor]); // Unmask the rounded area inside the rectangle + CGContextFillPath(context); + }]; + + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + [layer setContents:(id)[image CGImage]]; + self.layer.mask = layer; +} + #pragma mark Gesture recognition - (void)linkAction:(CCHLinkGestureRecognizer *)recognizer @@ -241,6 +271,10 @@ NSString *const CCHLinkAttributeName = @"CCHLinkAttributeName"; } [attributedText addAttributes:self.linkTextTouchAttributes range:range]; [super setAttributedText:attributedText]; + + if (self.linkCornerRadius > 0) { + [self drawRoundedCornerForRange:range]; + } }]; } @@ -253,6 +287,8 @@ NSString *const CCHLinkAttributeName = @"CCHLinkAttributeName"; } [attributedText addAttributes:self.linkTextAttributes range:range]; [super setAttributedText:attributedText]; + + self.layer.mask = nil; }]; } diff --git a/README.md b/README.md index 63afbb4..546c4ba 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,8 @@ The first method is called for taps, the second for long presses. To style the links, use `linkTextAttributes` and `linkTextTouchAttributes`. These dictionaries contain `NSAttributedString` attributes applied to links as they appear normally and when touched. By default, `linkTextAttributes` sets the tint color as foreground color and `linkTextTouchAttributes` a light gray background. +Use `linkCornerRadius` to make the background on touch as a rounded rectangle. + ### Advanced settings There are a few settings to allow you to adjust `CCHLinkTextView`'s behavior: