FRHyperLabel icon indicating copy to clipboard operation
FRHyperLabel copied to clipboard

HyperLinks not working

Open rahulbbit opened this issue 6 years ago • 2 comments

 FRHyperLabel *label = self.lblTermsAndPrivacyPolicy;
    label.numberOfLines = 0;
    NSString *string = @"By continuing you indicate that you have read and agree to the Terms Of Service and Privacy Policy";
    
    NSMutableParagraphStyle *style  = [[NSMutableParagraphStyle alloc] init];
    style.alignment= NSTextAlignmentCenter;
    
    NSDictionary *attributes ;
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad){
        attributes = @{NSForegroundColorAttributeName:[UIColor whiteColor],NSFontAttributeName:[UIFont fontWithName:@"Helvetica" size:20],NSParagraphStyleAttributeName:style};
    }
    else
    {
        attributes = @{NSForegroundColorAttributeName: [UIColor whiteColor],NSFontAttributeName:font13,NSParagraphStyleAttributeName:style,NSUnderlineStyleAttributeName:[NSNumber numberWithInt:NSUnderlineStyleNone]};
    }
    
    label.attributedText = [[NSAttributedString alloc]initWithString:string attributes:attributes];

//    [label setLinkAttributeDefault:attributes];
    
    //Step 2: Define a selection handler block
    void(^handler)(FRHyperLabel *label, NSString *substring) = ^(FRHyperLabel *label, NSString *substring){
        NSLog(@"%@",substring);
    };
    
    //Step 3: Add link substrings
    [label setLinksForSubstrings:@[@"Privacy Policy",@"Terms Of Service"] withLinkHandler:handler];

screen shot 2017-08-23 at 12 15 48 pm 1

i have written this code, still not working

rahulbbit avatar Aug 23 '17 06:08 rahulbbit

@rahulbbit Maybe this fix works for you too:

https://github.com/null09264/FRHyperLabel/issues/30

ghost avatar Sep 01 '17 11:09 ghost

I got the same issue that clicking on the link doesn't have any callback, even the text is colored properly. I figured out that this function - (NSInteger) characterIndexForPoint:(CGPoint) point always return -1, Not Found.

After an hour of searching in StackOverflow, I found the solution to the -1 problems here.

So, I extended FRHyperLabel as FRHyperLabelPatch and override - (NSInteger) characterIndexForPoint:(CGPoint) point

@implementation FRHyperLabelPatch

#pragma mark - Substring Locator

- (NSInteger) characterIndexForPoint:(CGPoint) point {

    // use Text Kit API in iOS 7:
    // Create instances of NSLayoutManager, NSTextContainer and NSTextStorage
    NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
    NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:CGSizeZero];
    NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:self.attributedText];

    // Configure layoutManager and textStorage
    [layoutManager addTextContainer:textContainer];
    [textStorage addLayoutManager:layoutManager];

    // Configure textContainer
    textContainer.lineFragmentPadding = 0.0;
    textContainer.lineBreakMode = self.lineBreakMode;
    textContainer.maximumNumberOfLines = self.numberOfLines;
    textContainer.size = self.bounds.size;

    CGPoint locationOfTouchInLabel = point;
    CGSize labelSize = self.bounds.size;
    CGRect textBoundingBox = [layoutManager usedRectForTextContainer:textContainer];
    CGPoint textContainerOffset = CGPointMake((labelSize.width - textBoundingBox.size.width) * 0.5 - textBoundingBox.origin.x,
                                              (labelSize.height - textBoundingBox.size.height) * 0.5 - textBoundingBox.origin.y);
    CGPoint locationOfTouchInTextContainer = CGPointMake(locationOfTouchInLabel.x - textContainerOffset.x,
                                                         locationOfTouchInLabel.y - textContainerOffset.y);
    NSInteger indexOfCharacter = NSNotFound;
    if (CGRectContainsPoint(textBoundingBox, locationOfTouchInLabel)) {
        indexOfCharacter = [layoutManager characterIndexForPoint:locationOfTouchInTextContainer
                                                 inTextContainer:textContainer
                        fractionOfDistanceBetweenInsertionPoints:nil];
    }
    return indexOfCharacter;
}

@end

However, now when clicking on the text, it sometimes give the wrong index. For example, my text has 16 Chinese characters while Range {0, 4} and Range {11, 4} are two links. When I clicking the second link, only 3 characters can return to my callback. I tried pixels by pixels and the returned character index are: 11, 12, 13, 15. It skipped 14.

After another hour of searching, I found an insight to the problem of above solution here. So, when I copy the label.text as label.attributedText, I need to include the font:

// Setup the tips label with two links
FRHyperLabel *label = self.tipsLabel;
label.attributedText = [[NSAttributedString alloc] initWithString:label.text
                                                       attributes:@{NSFontAttributeName: label.font}];

johncpang avatar Oct 15 '17 06:10 johncpang