it-swarm.com.ru

Как я могу сделать кликабельную ссылку в NSAttributedString?

Сделать гиперссылки кликабельными в UITextView тривиально. Вы просто устанавливаете флажок «обнаруживать ссылки» в представлении в IB, и он обнаруживает ссылки HTTP и превращает их в гиперссылки. 

Тем не менее, это все еще означает, что то, что видит пользователь, является «сырой» ссылкой. Файлы RTF и HTML позволяют настроить читаемую пользователем строку со ссылкой «позади». 

Атрибутивный текст легко установить в текстовое представление (или UILabel или UITextField, в этом отношении.) Однако, когда этот атрибутивный текст содержит ссылку, он не кликабелен.

Есть ли способ сделать читаемый пользователем текст кликабельным в UITextView, UILabel или UITextField?

Разметка отличается от SO, но вот общая идея. Что я хочу, так это текст:

Этот морф был создан с Face Dancer , Нажмите, чтобы посмотреть в магазине приложений.

Единственное, что я могу получить, это:

Этот морф был создан с помощью Face Dancer. Нажмите на http://example.com/facedancer для просмотра в магазине приложений.

164
Duncan C

Суть моего вопроса заключалась в том, что я хотел иметь возможность создавать кликабельные ссылки в текстовых представлениях/полях/метках без необходимости написания собственного кода для манипулирования текстом и добавления ссылок. Я хотел, чтобы это управлялось данными.

Я наконец-то понял, как это сделать. Проблема в том, что IB не соблюдает встроенные ссылки. 

Кроме того, версия NSAttributedString для iOS не позволяет инициализировать приписанную строку из файла RTF. Версия NSAttributedStringhas для OS X имеет инициализатор, который принимает файл RTF в качестве входных данных.

NSAttributedString соответствует протоколу NSCoding, поэтому вы можете преобразовать его в/из NSData

Я создал инструмент командной строки OS X, который принимает файл RTF в качестве входных данных и выводит файл с расширением .data, который содержит NSData из NSCoding. Затем я помещаю файл .data в свой проект и добавляю пару строк кода, который загружает текст в представление. Код выглядит так (этот проект был в Swift):

/*
If we can load a file called "Dates.data" from the bundle and convert it to an attributed string,
install it in the dates field. The contents contain clickable links with custom URLS to select
each date.
*/
if
  let datesPath = NSBundle.mainBundle().pathForResource("Dates", ofType: "data"),
  let datesString = NSKeyedUnarchiver.unarchiveObjectWithFile(datesPath) as? NSAttributedString
{
  datesField.attributedText = datesString
}

Для приложений, которые используют много форматированного текста, я создаю правило сборки, которое сообщает Xcode, что все файлы .rtf в данной папке являются исходными, а файлы .data - выходными. После этого я просто добавляю файлы .rtf в назначенный каталог (или редактирую существующие файлы), и процесс сборки выясняет, что они новые/обновленные, запускает инструмент командной строки и копирует файлы в комплект приложения. Работает красиво.

Я написал сообщение в блоге, которое ссылается на пример (Swift) проекта, демонстрирующего эту технику. Вы можете видеть это здесь:

Создание интерактивных URL-адресов в UITextField, которые открываются в вашем приложении

12
Duncan C

Используйте NSMutableAttributedString

NSMutableAttributedString * str = [[NSMutableAttributedString alloc] initWithString:@"Google"];
[str addAttribute: NSLinkAttributeName value: @"http://www.google.com" range: NSMakeRange(0, str.length)];
yourTextView.attributedText = str;

Правка:

Речь идет не о вопросе, а о том, чтобы уточнить: UITextField и UILabel не поддерживают открытие URL-адресов. Если вы хотите использовать UILabel со ссылками, вы можете проверить TTTAttributedLabel

Также вам следует установить значение dataDetectorTypes для вашего UITextView в UIDataDetectorTypeLink или UIDataDetectorTypeAll, чтобы открывать URL при нажатии. Или вы можете использовать метод делегата, как предложено в комментариях. 

139
ujell

Я нашел это действительно полезным, но мне нужно было сделать это во многих местах, поэтому я обернул свой подход простым расширением NSMutableAttributedString:

Swift 3

extension NSMutableAttributedString {

    public func setAsLink(textToFind:String, linkURL:String) -> Bool {

        let foundRange = self.mutableString.range(of: textToFind)
        if foundRange.location != NSNotFound {
            self.addAttribute(.link, value: linkURL, range: foundRange)
            return true
        }
        return false
    }
}

Swift 2

import Foundation

extension NSMutableAttributedString {

   public func setAsLink(textToFind:String, linkURL:String) -> Bool {

       let foundRange = self.mutableString.rangeOfString(textToFind)
       if foundRange.location != NSNotFound {
           self.addAttribute(NSLinkAttributeName, value: linkURL, range: foundRange)
           return true
       }
       return false
   }
}

Пример использования:

let attributedString = NSMutableAttributedString(string:"I love stackoverflow!")
let linkWasSet = attributedString.setAsLink("stackoverflow", linkURL: "http://stackoverflow.com")

if linkWasSet {
    // adjust more attributedString properties
}

Objective-C

Я только что выполнил требование сделать то же самое в чистом проекте Objective-C, так что вот категория Objective-C.

@interface NSMutableAttributedString (SetAsLinkSupport)

- (BOOL)setAsLink:(NSString*)textToFind linkURL:(NSString*)linkURL;

@end


@implementation NSMutableAttributedString (SetAsLinkSupport)

- (BOOL)setAsLink:(NSString*)textToFind linkURL:(NSString*)linkURL {

     NSRange foundRange = [self.mutableString rangeOfString:textToFind];
     if (foundRange.location != NSNotFound) {
         [self addAttribute:NSLinkAttributeName value:linkURL range:foundRange];
         return YES;
     }
     return NO;
}

@end

Пример использования:

NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:"I love stackoverflow!"];

BOOL linkWasSet = [attributedString setAsLink:@"stackoverflow" linkURL:@"http://stackoverflow.com"];

if (linkWasSet) {
    // adjust more attributedString properties
}

Удостоверьтесь, что атрибут Поведения NSTextField установлен как Выбираемый .  Xcode NSTextField behavior attribute

108
Karl Nosworthy

Я только что создал подкласс UILabel специально для таких случаев использования. Вы можете легко добавить несколько ссылок и определить для них разные обработчики. Он также поддерживает выделение нажатой ссылки при касании для обратной связи. Пожалуйста, обратитесь к https://github.com/null09264/FRHyperLabel .

В вашем случае код может выглядеть так: 

FRHyperLabel *label = [FRHyperLabel new];

NSString *string = @"This morph was generated with Face Dancer, Click to view in the app store.";
NSDictionary *attributes = @{NSFontAttributeName: [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline]};

label.attributedText = [[NSAttributedString alloc]initWithString:string attributes:attributes];

[label setLinkForSubstring:@"Face Dancer" withLinkHandler:^(FRHyperLabel *label, NSString *substring){
    [[UIApplication sharedApplication] openURL:aURL];
}];

Sample Screenshot (в этом случае обработчик настроен на выдачу предупреждения вместо открытия URL)

facedancer

30
Jinghan Wang

Незначительное улучшение решения ujell: если вы используете NSURL вместо NSString, вы можете использовать любой URL (например, пользовательские URL)

NSURL *URL = [NSURL URLWithString: @"whatsapp://app"];
NSMutableAttributedString * str = [[NSMutableAttributedString alloc] initWithString:@"start Whatsapp"];
[str addAttribute: NSLinkAttributeName value:URL range: NSMakeRange(0, str.length)];
yourTextField.attributedText = str;

Повеселись!

26
Hans One

У меня тоже было подобное требование, сначала я использовал UILabel, а потом понял, что UITextView лучше. Я заставил UITextView вести себя как UILabel, отключив взаимодействие и прокрутку, и создал метод категории для NSMutableAttributedString, чтобы установить ссылку на текст так же, как это делал Карл (+1 за это), это моя версия obj c

-(void)setTextAsLink:(NSString*) textToFind withLinkURL:(NSString*) url
{
    NSRange range = [self.mutableString rangeOfString:textToFind options:NSCaseInsensitiveSearch];

    if (range.location != NSNotFound) {

        [self addAttribute:NSLinkAttributeName value:url range:range];
        [self addAttribute:NSForegroundColorAttributeName value:[UIColor URLColor] range:range];
    }
}

вы можете использовать делегат ниже, чтобы обработать действие

- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)url inRange:(NSRange)characterRange
{
    // do the task
    return YES;
}
18
anoop4real

Используйте UITextView, он поддерживает интерактивные ссылки . Создайте приписанную строку, используя следующий код

NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:strSomeTextWithLinks];

Затем установите текст UITextView следующим образом

NSDictionary *linkAttributes = @{NSForegroundColorAttributeName: [UIColor redColor],

                                 NSUnderlineColorAttributeName: [UIColor blueColor],

                                 NSUnderlineStyleAttributeName: @(NSUnderlinePatternSolid)};

customTextView.linkTextAttributes = linkAttributes; // customizes the appearance of links
textView.attributedText = attributedString;

Убедитесь, что вы включили «Выбираемое» поведение UITextView в XIB.

15
Nitheesh George

Свифт 4:

var string = "Google"
var attributedString = NSMutableAttributedString(string: string, attributes:[NSAttributedStringKey.link: URL(string: "http://www.google.com")!])

yourTextView.attributedText = attributedString

Swift 3.1:

var string = "Google"
var attributedString = NSMutableAttributedString(string: string, attributes:[NSLinkAttributeName: URL(string: "http://www.google.com")!])

yourTextView.attributedText = attributedString
12
Bill Chan

Пример Swift 3 для обнаружения действий при атрибуции текстовых нажатий 

https://stackoverflow.com/a/44226491/5516830

let termsAndConditionsURL = TERMS_CONDITIONS_URL;
let privacyURL            = PRIVACY_URL;

override func viewDidLoad() {
    super.viewDidLoad()

    self.txtView.delegate = self
    let str = "By continuing, you accept the Terms of use and Privacy policy"
    let attributedString = NSMutableAttributedString(string: str)
    var foundRange = attributedString.mutableString.range(of: "Terms of use") //mention the parts of the attributed text you want to tap and get an custom action
    attributedString.addAttribute(NSLinkAttributeName, value: termsAndConditionsURL, range: foundRange)
    foundRange = attributedString.mutableString.range(of: "Privacy policy")
    attributedString.addAttribute(NSLinkAttributeName, value: privacyURL, range: foundRange)
    txtView.attributedText = attributedString
}

func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange) -> Bool {
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let vc = storyboard.instantiateViewController(withIdentifier: "WebView") as! SKWebViewController

    if (URL.absoluteString == termsAndConditionsURL) {
        vc.strWebURL = TERMS_CONDITIONS_URL
        self.navigationController?.pushViewController(vc, animated: true)
    } else if (URL.absoluteString == privacyURL) {
        vc.strWebURL = PRIVACY_URL
        self.navigationController?.pushViewController(vc, animated: true)
    }
    return false
}

Также вы можете добавить любое действие, которое захотите, с помощью метода shouldInteractWith URLUITextFieldDelegate.

Ура !!

9
Akila Wasala

Я написал метод, который добавляет ссылку (linkString) в строку (fullString) с определенным URL (urlString): 

- (NSAttributedString *)linkedStringFromFullString:(NSString *)fullString withLinkString:(NSString *)linkString andUrlString:(NSString *)urlString
{
    NSRange range = [fullString rangeOfString:linkString options:NSLiteralSearch];
    NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:fullString];

    NSMutableParagraphStyle *paragraphStyle = NSMutableParagraphStyle.new;
    paragraphStyle.alignment = NSTextAlignmentCenter;
    NSDictionary *attributes = @{NSForegroundColorAttributeName:RGB(0x999999),
                                 NSFontAttributeName:[UIFont fontWithName:@"HelveticaNeue-Light" size:10],
                                 NSParagraphStyleAttributeName:paragraphStyle};
    [str addAttributes:attributes range:NSMakeRange(0, [str length])];
    [str addAttribute: NSLinkAttributeName value:urlString range:range];

    return str;
}

Вы должны назвать это так: 

NSString *fullString = @"A man who bought the Google.com domain name for $12 and owned it for about a minute has been rewarded by Google for uncovering the flaw.";
NSString *linkString = @"Google.com";
NSString *urlString = @"http://www.google.com";

_youTextView.attributedText = [self linkedStringFromFullString:fullString withLinkString:linkString andUrlString:urlString];
4
wzbozon

Swift версия:

    // Attributed String for Label
    let plainText = "Apkia"
    let styledText = NSMutableAttributedString(string: plainText)
    // Set Attribuets for Color, HyperLink and Font Size
    let attributes = [NSFontAttributeName: UIFont.systemFontOfSize(14.0), NSLinkAttributeName:NSURL(string: "http://apkia.com/")!, NSForegroundColorAttributeName: UIColor.blueColor()]
    styledText.setAttributes(attributes, range: NSMakeRange(0, plainText.characters.count))
    registerLabel.attributedText = styledText
3
ioopl

Обновление:

На мой вопрос было 2 ключевых части:

  1. Как создать ссылку, в которой текст, отображаемый для кликабельной ссылки, отличается от действительной ссылки, которая вызывается:
  2. Как настроить ссылки без необходимости использовать пользовательский код для установки атрибутов в тексте.

Оказывается, в iOS 7 добавлена ​​возможность загрузки атрибутивного текста из NSData.

Я создал собственный подкласс UITextView, который использует атрибут @IBInspectable и позволяет загружать содержимое из файла RTF непосредственно в IB. Вы просто вводите имя файла в IB, а пользовательский класс делает все остальное.

Вот подробности:

В iOS 7 NSAttributedString получил метод initWithData:options:documentAttributes:error:. Этот метод позволяет загрузить NSAttributedString из объекта NSData. Сначала вы можете загрузить файл RTF в NSData, а затем использовать initWithData:options:documentAttributes:error:, чтобы загрузить эти NSData в текстовое представление. (Обратите внимание, что есть также метод initWithFileURL:options:documentAttributes:error:, который будет загружать приписанную строку непосредственно из файла, но этот метод устарел в iOS 9. Безопаснее использовать метод initWithData:options:documentAttributes:error:, который не устарел.

Я хотел метод, который позволял бы мне устанавливать кликабельные ссылки в моих текстовых представлениях без необходимости создавать какой-либо код, специфичный для ссылок, которые я использовал.

Решение, которое я придумал, состояло в том, чтобы создать собственный подкласс UITextView, который я называю RTF_UITextView, и присвоить ему свойство @IBInspectable с именем RTF_Filename. Добавление атрибута @IBInspectable к свойству заставляет Интерфейсный Разработчик выставить это свойство в «Инспекторе Атрибутов». Затем вы можете установить это значение из IB без специального кода.

Я также добавил атрибут @IBDesignable в свой пользовательский класс. Атрибут @IBDesignable сообщает Xcode, что он должен установить рабочую копию вашего пользовательского класса представления в Интерфейсный конструктор, чтобы вы могли видеть его на графическом экране иерархии вашего представления. () К сожалению, для этого класса свойство @IBDesignable кажется ненадежным. Это сработало, когда я впервые добавил его, но затем я удалил текстовое содержимое моего текстового представления, и кликабельные ссылки в моем представлении исчезли, и я не смог их вернуть.)

Код для моего RTF_UITextView очень прост. Помимо добавления атрибута @IBDesignable и свойства RTF_Filename с атрибутом @IBInspectable, я добавил метод didSet() в свойство RTF_Filename. Метод didSet() вызывается каждый раз, когда изменяется значение свойства RTF_Filename. Код для метода didSet() довольно прост:

@IBDesignable
class RTF_UITextView: UITextView
{
  @IBInspectable
  var RTF_Filename: String?
    {
    didSet(newValue)
    {
      //If the RTF_Filename is nil or the empty string, don't do anything
      if ((RTF_Filename ?? "").isEmpty)
      {
        return
      }
      //Use optional binding to try to get an URL to the
      //specified filename in the app bundle. If that succeeds, try to load
      //NSData from the file.
      if let fileURL = NSBundle.mainBundle().URLForResource(RTF_Filename, withExtension: "rtf"),

        //If the fileURL loads, also try to load NSData from the URL.
        let theData = NSData(contentsOfURL: fileURL)
      {
        var aString:NSAttributedString
        do
        {
          //Try to load an NSAttributedString from the data
          try
            aString = NSAttributedString(data: theData,
              options: [:],
              documentAttributes:  nil
          )
          //If it succeeds, install the attributed string into the field.
          self.attributedText = aString;
        }
        catch
        {
          print("Nerp.");
        }
      }

    }
  }
}

Обратите внимание, что если свойство @IBDesignable не позволяет надежно предварительно просматривать стилизованный текст в Интерфейсном конструкторе, то может быть лучше установить приведенный выше код как расширение UITextView, а не как пользовательский подкласс. Таким образом, вы можете использовать его в любом текстовом представлении, не меняя текстовое представление на пользовательский класс.

Смотрите мой другой ответ, если вам нужно поддерживать версии iOS до iOS 7.

Вы можете скачать пример проекта, который включает этот новый класс, с gitHub:

Демонстрационный проект DatesInSwift на Github

3
Duncan C

Просто найдите решение без кода для UITextView:  enter image description here

Включите Обнаружение-> Параметры ссылок, URL-адрес, а также адрес электронной почты будут обнаружены и кликабельны!

3
Bill Chan

Мне нужно было продолжать использовать чистый UILabel, так называемый это из моего распознавателя касаний (это основано на ответе malex здесь: Индекс символов в точке касания для UILabel )

UILabel* label = (UILabel*)gesture.view;
CGPoint tapLocation = [gesture locationInView:label];

// create attributed string with paragraph style from label

NSMutableAttributedString* attr = [label.attributedText mutableCopy];
NSMutableParagraphStyle* paragraphStyle = [NSMutableParagraphStyle new];
paragraphStyle.alignment = label.textAlignment;

[attr addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, label.attributedText.length)];

// init text storage

NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:attr];
NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
[textStorage addLayoutManager:layoutManager];

// init text container

NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:CGSizeMake(label.frame.size.width, label.frame.size.height+100) ];
textContainer.lineFragmentPadding  = 0;
textContainer.maximumNumberOfLines = label.numberOfLines;
textContainer.lineBreakMode        = label.lineBreakMode;

[layoutManager addTextContainer:textContainer];

// find tapped character

NSUInteger characterIndex = [layoutManager characterIndexForPoint:tapLocation
                                                  inTextContainer:textContainer
                         fractionOfDistanceBetweenInsertionPoints:NULL];

// process link at tapped character

[attr enumerateAttributesInRange:NSMakeRange(characterIndex, 1)
                                         options:0
                                      usingBlock:^(NSDictionary<NSString *,id> * _Nonnull attrs, NSRange range, BOOL * _Nonnull stop) {
                                          if (attrs[NSLinkAttributeName]) {
                                              NSString* urlString = attrs[NSLinkAttributeName];
                                              NSURL* url = [NSURL URLWithString:urlString];
                                              [[UIApplication sharedApplication] openURL:url];
                                          }
                                      }];
3
masty

Быстрое добавление к оригинальному описанию Дункана С в отношении поведения IB. Он пишет: «Сделать гиперссылки кликабельными в UITextView просто. Вы просто устанавливаете флажок« обнаруживать ссылки »в представлении в IB, и он обнаруживает ссылки http и превращает их в гиперссылки».

Мой опыт (по крайней мере, в xcode 7) заключается в том, что вам также нужно отключить поведение «Редактируемый», чтобы URL-адреса были обнаружены и кликабельны.

2
sakumatto

Используйте UITextView и установите dataDetectorTypes для Link.

как это:

testTextView.editable = false 
testTextView.dataDetectorTypes = .link

Если вы хотите определить ссылку, номер телефона, адрес и т.д. Затем

testTextView.dataDetectorTypes = .all
2
Adarsh G J

Если вы хотите использовать NSLinkAttributeName в UITextView, то вы можете рассмотреть возможность использования библиотеки AttributedTextView. Это подкласс UITextView, который очень легко справляется с ними. Для получения дополнительной информации см .: https://github.com/evermeer/AttributedTextView

Вы можете заставить любую часть текста взаимодействовать следующим образом (где textView1 - это UITextView IBoutlet):

textView1.attributer =
    "1. ".red
    .append("This is the first test. ").green
    .append("Click on ").black
    .append("evict.nl").makeInteract { _ in
        UIApplication.shared.open(URL(string: "http://evict.nl")!, options: [:], completionHandler: { completed in })
    }.underline
    .append(" for testing links. ").black
    .append("Next test").underline.makeInteract { _ in
        print("NEXT")
    }
    .all.font(UIFont(name: "SourceSansPro-Regular", size: 16))
    .setLinkColor(UIColor.purple) 

А для обработки хэштегов и упоминаний вы можете использовать такой код:

textView1.attributer = "@test: What #hashtags do we have in @evermeer #AtributedTextView library"
    .matchHashtags.underline
    .matchMentions
    .makeInteract { link in
        UIApplication.shared.open(URL(string: "https://Twitter.com\(link.replacingOccurrences(of: "@", with: ""))")!, options: [:], completionHandler: { completed in })
    }
1
Edwin Vermeer

Быстрый ответ - использование UITextView вместо UILabel. Вам необходимо включить Selectable и отключить Editable.

Затем отключите индикаторы прокрутки и отскоки.

Screen Shot

Screen Shot

Мое решение с использованием NSMutableAttributedString из строки html NSHTMLTextDocumentType

NSString *s = @"<p><a href='https://iTunes.Apple.com/us/app/xxxx/xxxx?mt=8'>https://iTunes.Apple.com/us/app/xxxx/xxxx?mt=8</a></p>";

NSMutableAttributedString *text = [[NSMutableAttributedString alloc]
                                           initWithData: [s dataUsingEncoding:NSUnicodeStringEncoding]
                                           options: @{ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType }
                                           documentAttributes: nil
                                           error: nil
                                           ];

cell.content.attributedText = text;
1
Dody Rachmat Wicaksono

Отличная библиотека от @AliSoftwareOHAttributedStringAdditions позволяет легко добавлять ссылки в UILabel вот документация: https://github.com/AliSoftware/OHAttributedStringAdditions/wiki/link-in-UILabel

0
iGranDav
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:strSomeTextWithLinks];

NSDictionary *linkAttributes = @{NSForegroundColorAttributeName: [UIColor redColor],   
                                 NSUnderlineColorAttributeName: [UIColor blueColor],
                                 NSUnderlineStyleAttributeName: @(NSUnderlinePatternSolid)};

customTextView.linkTextAttributes = linkAttributes; // customizes the appearance of links
textView.attributedText = attributedString;

КЛЮЧЕВЫЕ МОМЕНТЫ:

  • Убедитесь, что вы включили «Выбираемое» поведение UITextView в XIB.
  • Убедитесь, что вы отключили «редактируемое» поведение UITextView в XIB.
0
Shashank Sharma

Если у вас возникли проблемы с тем, что @Karl Nosworthy и @esilver предоставили выше, я обновил расширение NSMutableAttributedString до его версии Swift 4.

extension NSMutableAttributedString {

public func setAsLink(textToFind:String, linkURL:String) -> Bool {

    let foundRange = self.mutableString.range(of: textToFind)
    if foundRange.location != NSNotFound {
         _ = NSMutableAttributedString(string: textToFind)
        // Set Attribuets for Color, HyperLink and Font Size
        let attributes = [NSFontAttributeName: UIFont.bodyFont(.regular, shouldResize: true), NSLinkAttributeName:NSURL(string: linkURL)!, NSForegroundColorAttributeName: UIColor.blue]

        self.setAttributes(attributes, range: foundRange)
        return true
    }
    return false
  }
}
0
Vick Swift

если вы хотите активную подстроку в вашем UITextView, то вы можете использовать мой расширенный TextView ... он короткий и простой. Вы можете редактировать его как хотите.

результат:  enter image description here

код: https://github.com/marekmand/ActiveSubstringTextView

0
Marek Manduch