2

I am using a UITextView to make hashtags selectable. It detects taps perfectly. My issue is with the selection color. It looks black and I wanted the text to fade a bit on selection instead. Here's what I've got now:

screenshot

I've tried changing the tintColor, the NSForegroundColorAttributeName, and the NSBackgroundColorAttributeName but it doesn't work.

JAL
  • 41,701
  • 23
  • 172
  • 300
jonypz
  • 1,515
  • 1
  • 20
  • 35

3 Answers3

2

There is no documented property for the selected or highlighted color of detected links, but you should be able to achieve the same effect by overriding the delegate method textView:shouldInteractWithURL:inRange: and changing the color yourself.

From the UITextViewDelegate protocol reference:

The text view calls this method if the user taps or long-presses the URL link. Implementation of this method is optional. By default, the text view opens the application responsible for handling the URL type and passes it the URL. You can use this method to trigger an alternative action, such as displaying the web content at the URL in a web view within the current application.

The last parameter is an NSRange object called characterRange, which represents the character range containing the tapped URL (or hashtag). Using that range, you should be able to add attributes such as NSForegroundColorAttributeName so as to change only the color of the particular hashtag that was tapped.

You'll probably want to revert any changes on touchesEnded and touchesCancelled.

Alternatively, you could make your own subclass and manually handle the above.

Community
  • 1
  • 1
jamesk
  • 3,807
  • 21
  • 38
2

Although there is no public API to do this, I was curious and decided to dig through the private header for UITextField. I found that there is a class method on UITextField _sharedHighlightView which returns an instance of the private _UIHighlightView class. This is the class in charge of the highlighting. Swizzling _sharedHighlightView and changing its color will allow you to change the color of any data-detected links:

WARNING: This is a hack that uses method swizzling and private APIs/properties.

class MyTextView: UITextView {

    var newHighlightView: AnyObject?

    func changeHighlight() {
        self.newHighlightView = UITextView.performSelector(Selector("_sharedHighlightView")).takeUnretainedValue()
        self.newHighlightView?.setValue(UIColor.redColor().colorWithAlphaComponent(0.6), forKey: "_color")

        let originalHighlightView = class_getClassMethod(MyTextView.self, Selector("_sharedHighlightView"))
        let newHighlightView = class_getClassMethod(MyTextView.self, #selector(MyTextView.swizzleHighlightView))
        method_exchangeImplementations(originalHighlightView, newHighlightView)
    }

    func swizzleHighlightView() -> AnyObject {
        return self.newHighlightView!
    }
}

In your View Controller:

let textView = MyTextView(frame: CGRect(x: 0, y: 40.0, width: 200.0, height: 200.0))
textView.dataDetectorTypes = .All
textView.editable = false
textView.text = "Some text.  http://www.google.com/"
textView.changeHighlight()
self.view.addSubview(textView)

Result:

Highlight color changed

This could probably be cleaned up a little further by not force-unwrapping any optionals.

JAL
  • 41,701
  • 23
  • 172
  • 300
-1

Work around for this can be done, you can use UIButton instead of textview. By using button you can have the same effect.

Aneesh
  • 107
  • 7
  • I am using a textview on purpose. To have multiple action points. That's not possible with an uibutton – jonypz May 06 '16 at 17:30