TextureGroup / Texture

Smooth asynchronous user interfaces for iOS apps.
https://texturegroup.org/
Other
8.02k stars 1.29k forks source link

Detect tap on hashtags and add action targets on ASTextNode #1363

Closed lohenyumnam closed 5 years ago

lohenyumnam commented 5 years ago

Can any one point me to right direction. I want to detect tap on hashtags and add action targets on ASTextNode

ay8s commented 5 years ago

You could use something like twitter-text to detect the entities. Then use those ranges to add a attributes to the hashtags, including a URL.


NSMutableDictionary *linkAttributes = [[NSMutableDictionary alloc] initWithDictionary:@{NSForegroundColorAttributeName : [UIColor whiteColor]}];
linkAttributes[@"TextLinkAttributeNameURL"] = [NSURL URLWithString:url];
[string addAttributes:linkAttributes range:range];```
lohenyumnam commented 5 years ago

Here is the Solution base on the @ay8s 's guide In Slack

import UIKit
import AsyncDisplayKit
import twitter_text

class ViewController:  ASViewController<ASDisplayNode> {
    private var kLinkAttributeName = "PlaceKittenNodeLinkAttributeName"

    let textNode = ASTextNode()

    let text: NSString = "#Spotify is now free on #mobile and tablet. Listen to the right #music and #podcasts, wherever you are. With #Spotify, you have access to a world of #music and @Lohen"

    init() {
        super.init(node: .init())
        self.node.automaticallyManagesSubnodes = true
        self.node.automaticallyRelayoutOnSafeAreaChanges = true
        self.node.isOpaque = true
        self.node.layoutSpecBlock = {
            [weak self] (_, _) -> ASLayoutSpec in
            guard let self = self else { return ASLayoutSpec() }
            let centerSpec = ASCenterLayoutSpec(centeringOptions: .XY, sizingOptions: [], child: self.textNode)
            let layout = ASInsetLayoutSpec(insets: UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0), child: self.textNode)
            return centerSpec
        }

    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        textNode.delegate = self
        textNode.isUserInteractionEnabled = true
        view.backgroundColor = .white

        let updateString = NSMutableAttributedString(string: text as String)

        let entities = TwitterText.entities(inText: text as String)
        var tag: String = ""
        var tags: [String] = [String]()

        for entity: TwitterTextEntity in entities  {
            let r: NSRange = entity.range

            if entity.type == TwitterTextEntityType.hashtag {
                tag = text.substring(with: r)
                print(tag)
                let url = URL(string: tag)
                if url != nil {
                    var mutableActiveLinkAttributes: [AnyHashable : Any] = [:]
                    mutableActiveLinkAttributes[NSAttributedString.Key.foregroundColor] = UIColor.red

                    if let url = URL(string: url?.absoluteString ?? "") {
                        mutableActiveLinkAttributes[tag] = url
                        tags.append(tag)
                    }

                    if let mutableActiveLinkAttributes = mutableActiveLinkAttributes as? [NSAttributedString.Key : Any] {
                        updateString.addAttributes(mutableActiveLinkAttributes, range: r)
                    }
                }
            }

            if entity.type == TwitterTextEntityType.screenName {
                tag = text.substring(with: r)
                print(tag)
                let url = URL(string: tag)
                if url != nil {
                    var mutableActiveLinkAttributes: [AnyHashable : Any] = [:]
                    mutableActiveLinkAttributes[NSAttributedString.Key.foregroundColor] = UIColor.blue

                    if let url = URL(string: url?.absoluteString ?? "") {
                        mutableActiveLinkAttributes[tag] = url
                        tags.append(tag)
                    }

                    if let mutableActiveLinkAttributes = mutableActiveLinkAttributes as? [NSAttributedString.Key : Any] {
                        updateString.addAttributes(mutableActiveLinkAttributes, range: r)
                    }
                }
            }

        }
        textNode.linkAttributeNames = tags
        textNode.attributedText = updateString

    }

}

extension ViewController: ASTextNodeDelegate {
    func textNode(_ textNode: ASTextNode!, tappedLinkAttribute attribute: String!, value: Any!, at point: CGPoint, textRange: NSRange) {
        if let tag = attribute{
            print(tag)
        }

    }
}