美文网首页
UITextView富文本设置

UITextView富文本设置

作者: cyh老崔 | 来源:发表于2017-11-07 19:47 被阅读532次

前言

最近项目中需要对UITextView中输入的文本作行高设置, 本来是个很简单的需求, 最后实现起来却费了好多功夫.

实现思路

以下是我的实现方式, 如果有需要改进的地方, 还请各位指出:

  1. 每次文本增加时(即不包括删除), 给UITextView设置属性文本
  2. 重置光标位置, 因为上步设置过属性文本后,光标移到最后面

代码

下面的代码可能比较碎, 因为我剥离了一些业务逻辑, 但是不妨碍阅读.

  1. 设置属性文本
- (void)textViewDidChange:(UITextView *)textView{
    
    [self setAttributedString:textView.text forTextView:textView];
}

1.1 步骤1中的方法:

- (void)setAttributedString:(NSString *)string forTextView:(UITextView *)textView{
    
    if (!isSetAttr_) {
        return;
    }
    
    ///1.设置成富文本
    NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:string attributes:[self attributeForTextView]];
    textView.attributedText = attrString;
    
}

1.1.1 步骤1.1中的方法

- (nullable NSDictionary<NSAttributedStringKey, id> *)attributeForTextView{
    
    NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
    paragraphStyle.lineSpacing = 7;
    NSDictionary *attr = @{
                           NSFontAttributeName : [UIFont systemFontOfSize:14],
                           NSParagraphStyleAttributeName : paragraphStyle
                           };
    return attr;
}

1.1 中的isSetAttr_的赋值来自这个代理方法:

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text

因为上述方法调用顺序在

- (void)textViewDidChange:(UITextView *)textView

之前. 从字面就可以理解:

  • 前者意思是: 可以替换吗? 如果你回答了可以替换(return YES)
  • 后台意思是: 已经替换了.
  1. 设置光标位置, 及赋值上述isSetAttr_
static NSRange lastRange_;
static BOOL isSetAttr_;
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        
        if (text.length != 0) { //不是删除文本
            textView.selectedRange = NSMakeRange(lastRange_.location+text.length, 0);
        }
        [self setContentOffsetWithCursorLocation:lastRange_.location textView:textView];
    });
    lastRange_ = range;
    isSetAttr_ = text.length != 0;
    
    return YES;
}

此处有两个细节:

  • text.length == 0时, 说明用户在删除文本
  • 使用dispatch_after延迟的原因, 是在stackerflow上面得到的一个回答. 抱歉链接找不到了. 如果不添加的话, 你就会发现在正常速度文本变化时, 光标位置设置错误.
    ps: 就像许多UI的操作一样, 如果你不知道代码哪里出了问题, 可以尝试延迟

最后还有一个小问题, 按照抽取方法的原则. isSetAttr_不应该在方法内部判断, 应该作为一个标志参数传入方法中.最终效果如下:

textView.gif

相关文章

网友评论

      本文标题:UITextView富文本设置

      本文链接:https://www.haomeiwen.com/subject/ziajmxtx.html