美文网首页
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