美文网首页
iOS + 根据UITextView获取任一字符位置、末尾字符位

iOS + 根据UITextView获取任一字符位置、末尾字符位

作者: YaoYaoX | 来源:发表于2019-09-30 19:32 被阅读0次

需求:设置标题,最多显示两行,多余的字符串以"..."截断,并在标题末尾追加编辑按钮

  1. 获取UITextView中任一字符位置

     - (CGRect)rectOfCharacterAtIndex:(NSInteger)index inTextView:(UITextView *)textView {
         if (!textView) {
             return CGRectZero;
         }
        
         NSString *text = textView.text;
         if (index <= 0 && index >= text.length) {
             return CGRectZero;
         }
         
         // 获取每个字符的位置
         [textView setSelectedRange:NSMakeRange(index,1)];
         NSArray<UITextSelectionRect *> *rects = [textView selectionRectsForRange:textView.selectedTextRange];
         [textView setSelectedRange:NSMakeRange(0, 0)];
         
         // 获取字符有效的位置
         CGRect charRect = rects.firstObject.rect;
         for (UITextSelectionRect *rect in rects) {
             // rect有效的情况下
             if (rect.rect.size.width > 0 && rect.rect.size.height > 0) {
                 if (CGRectGetMinY(charRect) <  CGRectGetMinY(rect.rect)) {
                     charRect = rect.rect;
                 } else if (CGRectGetMinY(charRect) == CGRectGetMinY(rect.rect) && CGRectGetMinX(charRect) < CGRectGetMinX(rect.rect)) {
                     charRect = rect.rect;
                 }
             }
         }
    
         return charRect;
     }
    
  2. 获取每一行字符串的长度及该行最后一个字符下标

     // 计算每一行的rect及最后一个字符的下标
     - (NSArray *)lineInformaitonOfTextView:(UITextView *)textView {
         NSString *text = textView.text;
         NSMutableDictionary<NSString *, NSDictionary *> *lineInfo = [NSMutableDictionary dictionary];
         for (NSInteger index = 0; index < text.length; index++) {
             CGRect charRect = [self rectOfCharacterAtIndex:index inTextView:textView];
             NSString *YKey = [NSString stringWithFormat:@"%.0f", charRect.origin.y];
             NSMutableDictionary *info = [lineInfo[YKey] mutableCopy];
             if (!info) {
                 info = [NSMutableDictionary dictionary];
             }
             
             info[@"lastCharIndex"] = @(index);
             
             if (!info[@"rect"]) {
                 info[@"rect"] = [NSValue valueWithCGRect:charRect];
             } else {
                 CGRect rect = [info[@"rect"] CGRectValue];
                 if (rect.origin.x > charRect.origin.x) {
                     rect.origin.x = charRect.origin.x;
                 }
                 if (rect.origin.y > charRect.origin.y) {
                     rect.origin.y = charRect.origin.y; 
                 }
                 if (CGRectGetMaxX(rect) < CGRectGetMaxX(charRect)) {
                     rect.size.width = CGRectGetMaxX(charRect) - CGRectGetMinX(rect);
                 }
                 if (CGRectGetMaxY(rect) < CGRectGetMaxY(charRect)) {
                     rect.size.height = CGRectGetMaxY(charRect) - CGRectGetMinY(rect); 
                 }
                 info[@"rect"] = [NSValue valueWithCGRect:rect];
             }
             lineInfo[YKey] = info;
         }
         
         // 对行排序
         NSMutableArray *allYValue = [lineInfo.allKeys mutableCopy];
         [allYValue sortUsingComparator:^NSComparisonResult(NSString *obj1, NSString *obj2) {
             if (obj1.integerValue <= obj2.integerValue) {
                 return NSOrderedAscending;
             } else {
                 return NSOrderedDescending;
             }
         }];
         
         // 按行顺序返回数据
         NSMutableArray *lineArray = [NSMutableArray array];
         for (NSString *lineKey in allYValue) {
             [lineArray addObject:lineInfo[lineKey]];
         }
         return lineArray;
     }
    
  3. 限制行数、及限制最后一行的长度

     /** 限制行数且以...在末尾截断,最后一行末尾空出间隔追加控件
      * @param numberOfLine 限制行数
      * @param appendLength 最后一行的末尾空白区
     */
     - (void)setString:(NSString *)string attributes:(NSDictionary *)attributes textView:(UITextView *)textView maxNumberOfLine:(NSInteger)numberOfLine appendLength:(CGFloat)appendLength {
         if (!textView) {
             return ;
         }
         
         // 设置字符串
         string = [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
         textView.text = string;
         if (attributes && string) {
             textView.text = nil;
             NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc] initWithString:string attributes:attributes];
             textView.attributedText = attributeString;
         }
         CGRect textFrame = textView.frame;
         textFrame.size.height = [textView sizeThatFits:CGSizeMake(textFrame.size.width, MAXFLOAT)].height;
         textView.frame = textFrame;
         
         // 获取每一行字符串位置
         NSArray *lineInfoArray = [self lineInformaitonOfTextView:textView];
         
         // 当行号等于或超过限制行数时,需调整最后一行的字符,以便能空出appendLength的位置
         if (lineInfoArray.count >= numberOfLine) {
             NSDictionary *lineInfo = lineInfoArray[numberOfLine - 1];
             CGFloat adjustLastLineLength = CGRectGetMaxX([lineInfo[@"rect"] CGRectValue]); // 调整过后,最后一行字符的宽度
             NSInteger adjustIndex = [lineInfo[@"lastCharIndex"] integerValue]; // 调整过后,字符开始截断的位置
             // 最后一行的空余位置不够appendLength时,才需要偏移
             if (adjustIndex > 0 && adjustLastLineLength + appendLength > textFrame.size.width) {
                 // 偏移下标,空出appendLength的位置
                 for (; adjustIndex > 0; adjustIndex--) {
                     CGRect charRect = [self rectOfCharacterAtIndex:adjustIndex inTextView:textView];
                     if (CGRectGetMinX(charRect) + appendLength < textFrame.size.width) {
                         break;
                     }
                 }
                 
                 // 截断字符串
                 NSString *adjustText = textView.text;
                 if (adjustIndex >= 0 && adjustIndex < adjustText.length) {
                     adjustText = [adjustText stringByReplacingCharactersInRange:NSMakeRange(adjustIndex, adjustText.length - adjustIndex) withString:@"..."];
                     // 重新设置值
                     textView.text = adjustText;
                     if (attributes && adjustText) {
                         textView.text = nil;
                         NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc] initWithString:adjustText attributes:attributes];
                         textView.attributedText = attributeString;
                     }
                 }
             }
         }
         
         textFrame.size.height = [textView sizeThatFits:CGSizeMake(textFrame.size.width, MAXFLOAT)].height;
         textView.frame = textFrame;
     }
    

相关文章

网友评论

      本文标题:iOS + 根据UITextView获取任一字符位置、末尾字符位

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