【问题标题】:Replace UITextViews text with attributed string用属性字符串替换 UITextViews 文本
【发布时间】:2013-05-18 23:11:25
【问题描述】:

我有一个UITextView,当用户在其中输入文本时,我想即时格式化文本。语法高亮之类的...

为此,我想使用UITextView...

除了一个问题,一切正常:我从文本视图中获取文本并从中创建一个NSAttributedString。我对此属性字符串进行了一些编辑,并将其设置回textView.attributedText

每次用户键入时都会发生这种情况。所以我必须在编辑之前记住selectedTextRange attributedText 并在之后将其设置回来,以便用户可以在他之前输入的位置继续输入。唯一的问题是,一旦文本长到需要滚动,如果我输入缓慢,UITextView 现在将开始滚动到顶部。

这里是一些示例代码:

- (void)formatTextInTextView:(UITextView *)textView
{
  NSRange selectedRange = textView.selectedRange;
  NSString *text = textView.text;

  // This will give me an attributedString with the base text-style
  NSMutableAttributedString *attributedString = [self attributedStringFromString:text];

  NSError *error = nil;
  NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"#(\\w+)" options:0 error:&error];
  NSArray *matches = [regex matchesInString:text
                                    options:0
                                      range:NSMakeRange(0, text.length)];

  for (NSTextCheckingResult *match in matches)
  {
    NSRange matchRange = [match rangeAtIndex:0];
    [attributedString addAttribute:NSForegroundColorAttributeName
                             value:[UIColor redColor]
                             range:matchRange];
  }

  textView.attributedText = attributedString;
  textView.selectedRange = selectedRange;
}

有没有不直接使用CoreText的解决方案?我喜欢UITextViews 选择文本等功能......

【问题讨论】:

标签: ios uitextview core-text nsattributedstring


【解决方案1】:

我不确定这是不是正确的解决方案,但它确实有效。
只需在格式化文本之前禁用滚动并在格式化后启用它

- (void)formatTextInTextView:(UITextView *)textView
{
    textView.scrollEnabled = NO;
    NSRange selectedRange = textView.selectedRange;
    NSString *text = textView.text;

    // This will give me an attributedString with the base text-style
    NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:text];

    NSError *error = nil;
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"#(\\w+)" options:0 error:&error];
    NSArray *matches = [regex matchesInString:text
                                      options:0
                                        range:NSMakeRange(0, text.length)];

    for (NSTextCheckingResult *match in matches)
    {
        NSRange matchRange = [match rangeAtIndex:0];
        [attributedString addAttribute:NSForegroundColorAttributeName
                                 value:[UIColor redColor]
                                 range:matchRange];
    }

    textView.attributedText = attributedString;
    textView.selectedRange = selectedRange;
    textView.scrollEnabled = YES;
}

【讨论】:

  • 感谢您的回答!!! :) 与此同时,我找到了另一个解决方案......我只是将 UITextView 子类化并覆盖了'scrollRectToVisible:animated:',让它在没有动画的情况下调用超级......你的解决方案似乎更流畅了:) 再次,非常感谢!
  • 感谢您的回答。它给了我一个解决问题的想法。
  • Swift 5+ 的更新:NSForegroundColorAttributeName 应替换为 NSAttributedString.Key.foregroundColor
【解决方案2】:

Swift 2.0:

let myDisplayTxt:String = "Test String"

    let string: NSMutableAttributedString = NSMutableAttributedString(string: self.myDisplayTxt)
    string.addAttribute(NSForegroundColorAttributeName, value: UIColor.redColor(), range: NSMakeRange(0, 5))
    string.addAttribute(String(kCTForegroundColorAttributeName), value: UIColor.redColor().CGColor as AnyObject, range: NSMakeRange(0, 5))

    self.sampleTextView.attributedText =  string

【讨论】:

    【解决方案3】:

    自己使用了 Sergeys 的答案并将其移植到 Swift 2:

    func formatTextInTextView(textView: UITextView) {
        textView.scrollEnabled = false
        let selectedRange = textView.selectedRange
        let text = textView.text
    
        // This will give me an attributedString with the base text-style
        let attributedString = NSMutableAttributedString(string: text)
    
        let regex = try? NSRegularExpression(pattern: "#(\\w+)", options: [])
        let matches = regex!.matchesInString(text, options: [], range: NSMakeRange(0, text.characters.count))
    
        for match in matches {
            let matchRange = match.rangeAtIndex(0)
            attributedString.addAttribute(NSForegroundColorAttributeName, value: UIColor.redColor(), range: matchRange)
        }
    
        textView.attributedText = attributedString
        textView.selectedRange = selectedRange
        textView.scrollEnabled = true
    }
    

    【讨论】:

    • 什么时候调用这个方法?其实我想要和你的代码一样,但作为链接。你能分享那个代码吗?
    【解决方案4】:

    在 Swift 4 中:

    func createAttributedText() {
        let stringText = "Test String"
        let stringCount = stringText.count
        let string: NSMutableAttributedString = NSMutableAttributedString(string: stringText)
    
        string.addAttribute(NSForegroundColorAttributeName, value: UIColor.red, range: NSMakeRange(0, stringCount))
    
        self.textView.attributedText =  string
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-04
      • 2015-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-30
      • 1970-01-01
      相关资源
      最近更新 更多