How to create clickable label Like Facebook in ios?

485 views Asked by At

I am developing a social app in which I need show post and sharing etc. I also need to show tag friend.

When post is show on list UI is also similar to Facebook post. Please check below screen shot. enter image description here

As you can see Clicking Post title is as attributed single line, Where I need to open User Profile when user click on his name that is Person Name Abc and want to open Page when user click on Buzzfeed india,

As we need to use a UILabel to display content like this I am not able to get click on particular word. I have already tried https://github.com/null09264/FRHyperLabel but when there is multiple line Then clicking on word is not perfect.

2

There are 2 answers

4
Aravind A R On BEST ANSWER

You can use TTTAttributedLabel to make a particular part or words tappable in a UILabel.

For example

label.text = @"Fork me on GitHub!"; // Repository URL will be automatically detected and linked
NSRange range = [label.text rangeOfString:@"me"];
[label addLinkToURL:[NSURL URLWithString:@"meUrl"] withRange:range];

Here me becomes tappable and on tapping that word delegate method didSelectLinkWithURL gets called and you can check for that link inside that function

(void)attributedLabel:(TTTAttributedLabel *)label didSelectLinkWithURL:(NSURL *)url {
    NSLog(@"link %@", [url absoluteString]);
   if ([url absoluteString] == @"meUrl") {
   //implement your logic here
   }
    NSLog(@"whole label %@", label);
}
0
Yuyutsu On

Try using this:

Add Extension

extension UITapGestureRecognizer {

    func didTapAttributedTextInLabel(label: UILabel, inRange targetRange: NSRange) -> Bool {
        // Create instances of NSLayoutManager, NSTextContainer and NSTextStorage
        let layoutManager = NSLayoutManager()
        let textContainer = NSTextContainer(size: CGSize.zero)
        let textStorage = NSTextStorage(attributedString: label.attributedText!)

        // Configure layoutManager and textStorage
        layoutManager.addTextContainer(textContainer)
        textStorage.addLayoutManager(layoutManager)

        // Configure textContainer
        textContainer.lineFragmentPadding = 0.0
        textContainer.lineBreakMode = label.lineBreakMode
        textContainer.maximumNumberOfLines = label.numberOfLines
        let labelSize = label.bounds.size
        textContainer.size = labelSize

        // Find the tapped character location and compare it to the specified range
        let locationOfTouchInLabel = self.location(in: label)
        let textBoundingBox = layoutManager.usedRect(for: textContainer)
        let textContainerOffset = CGPoint(x:(labelSize.width - textBoundingBox.size.width) * 0.5 - textBoundingBox.origin.x,y:(labelSize.height - textBoundingBox.size.height) * 0.5 - textBoundingBox.origin.y);


        let locationOfTouchInTextContainer = CGPoint(x:locationOfTouchInLabel.x - textContainerOffset.x,y:locationOfTouchInLabel.y - textContainerOffset.y);
        let indexOfCharacter = layoutManager.characterIndex(for: locationOfTouchInTextContainer, in: textContainer, fractionOfDistanceBetweenInsertionPoints: nil)

        return NSLocationInRange(indexOfCharacter, targetRange)
    }

}

Then Add UITapGestureRecognizer on your UILable. Please make sure UILabel.isUserInteractionEnabled is true

override func viewDidLoad() {
        super.viewDidLoad()

        initialSetup()
    }

func initialSetup(){
    let tap = UITapGestureRecognizer(target: self, action: #selector(self.didTap(_:)))
    lblTitle.addGestureRecognizer(tap)
    lblTitle.isUserInteractionEnabled = true
    lblTitle.numberOfLines = 0
    let personname = "Person Name Abc"
    let buzzIndia = "Buzzfeed india"
    let str = "\(personname) shared \(buzzIndia)'s video"
    let attributedString = NSMutableAttributedString(string:str)

    let range = (str as NSString).range(of: personname)
    attributedString.addAttribute(NSForegroundColorAttributeName, value: UIColor.black, range: range)
    if let font = UIFont(name: "Helvetica Bold", size: 14) {
        attributedString.addAttribute(NSFontAttributeName, value: font, range: range)
    }

    let rangeBuzz = (str as NSString).range(of: buzzIndia)
    attributedString.addAttribute(NSForegroundColorAttributeName, value: UIColor.black, range: rangeBuzz)
    if let font = UIFont(name: "Helvetica Bold", size: 14) {
        attributedString.addAttribute(NSFontAttributeName, value: font, range: rangeBuzz)
    }

    lblTitle.attributedText = attributedString

}

func didTap(_ gesture: UITapGestureRecognizer) {
    let text = (lblTitle.text)!
    let name = (text as NSString).range(of: "Person Name Abc")
    let buzzfeed = (text as NSString).range(of: "Buzzfeed india")

    if gesture.didTapAttributedTextInLabel(label: lblTitle, inRange: name) {
        //Repective "Person Name Abc" action
        print("Person Name Abc")
    }else if gesture.didTapAttributedTextInLabel(label: lblTitle, inRange: buzzfeed) {
        //Repective "Buzzfeed india" action
        print("Buzzfeed india")
    }else {
        print("other tapped")
    }
}

Reference: http://samwize.com/2016/03/04/how-to-create-multiple-tappable-links-in-a-uilabel/