美文网首页iOS 功能类YYKit相关内容iOS开发-高级汇总
YYKit之YYText、YYLabel使用总结(更新)

YYKit之YYText、YYLabel使用总结(更新)

作者: Saylor_Lone | 来源:发表于2017-07-27 21:05 被阅读728次

1.索引

    [[IQKeyboardManager sharedManager] registerTextFieldViewClass:[YYTextView class]
                                  didBeginEditingNotificationName:YYTextViewTextDidBeginEditingNotification
                                    didEndEditingNotificationName:YYTextViewTextDidEndEditingNotification];
    //默认关闭IQKeyboard 在需要的界面启用
    [IQKeyboardManager sharedManager].enable = NO;
    [[IQKeyboardManager sharedManager] setEnableAutoToolbar:NO];
  • 布局问题

  • 如果配合AutoLayout 计算Size后务必更新约束

  • 目前能够保证没有问题的方法 SizeThatFits


//preferLayoutWidth布局指定宽度

CGSize fitSize =[self.txtContent sizeThatFits:CGSizeMake(preferLayoutWidth,CGFLOAT_MAX)];

//宽度修正_当文本中包含大量空格时,Size会出问题

float fixWidth = fitSize.width;

if(fitSize.width > preferLayoutWidth)

{

fixWidth = preferLayoutWidth;

}

  • 输入标点符号后,键盘不自动切换的问题。(对比UITextView)

  • 增加属性NumberOfLine、TruncationToken用于满足行数限制的个别需求(主要应用场景,带有选择菜单、文本选择、放大镜等效果的YYLabel)参见点#392

  • YYTextView的SuperView为UIScrollView时,文本选择及复制菜单的问题。

  • 修改YYKit源码,增加代理方法


YYTextView.h

@protocol YYTextViewSelectMenuDelegate

/**

*@brief在即将进入选择文本选择状态时调用

*/

-(void)textViewWillShowSelectMenu:(YYTextView *)textView;

/**

*@brief在即将推出选择文本选择状态时调用

*/

-(void)textViewWillHideSelectMenu:(YYTextView *)textView;

@end

YYTextView.m

-(void)_showMenu {

…//代码块最后

if([self.delegateSelectMenu  respondsToSelector:@selector(textViewWillShowSelectMenu:)]){

[self.delegateSelectMenu textViewWillShowSelectMenu:self];

}

}

-(void)_hideMenu {

if(_state.showingMenu){

_state.showingMenu = NO;

UIMenuController *menu =[UIMenuController sharedMenuController];

[menu setMenuVisible:NO animated:YES];

if([self.delegateSelectMenu respondsToSelector:@selector(textViewWillHideSelectMenu:)]){

[self.delegateSelectMenu textViewWillHideSelectMenu:self];

}

}

if(_containerView.isFirstResponder){

_state.ignoreFirstResponder = YES;

[_containerView resignFirstResponder];// it will call[self becomeFirstResponder],ignore it temporary.

_state.ignoreFirstResponder = NO;

}

}

  • 需求YYTextView添加控件后,需要自动更新ContentSize

  • YYTextView子类重写


-(void)setContentSize:(CGSize)contentSize{

//不影响其它的位置

//viewExPanle子类属性用于添加控件

if(!self.viewExPanle){

[super setContentSize:contentSize];

return;

}

//实际文本内容Size

CGSize txtSize = self.textLayout.textBoundingSize;

if(txtSize.width > self.preferredMaxLayoutWidth){

txtSize.width = self.preferredMaxLayoutWidth;

}

CGFloat fltExControlHeight = 0;

//这里必须要获取真实的数据

if(!self.viewExPanle.hidden){

fltExControlHeight += self.viewExPanle.height

self.fltExTopMargin;//fltExTopMargin子类属性,控件与文本的间距

}

txtSize.height += fltExControlHeight;

[super setContentSize:txtSize];

}

//子类方法提供外部调用以更新ContentSize

-(void)updateContentSizeByExPanleChange{

if(!self.viewExPanle){

return;

}

//只为触发方法设置

[self setContentSize:CGSizeZero];

}

  • 为了调整文本行间距在子类中设置了linePositionModifier,可以给子类暴露一些方法,可自定义行间距参见YYKit Demo WBTextLinePositionModifier

  • 为了适应需求(表情特么不规范!!!),表情在文本中宽度自由


YYTextUtilities.h

新增

/**

Get the `AppleColorEmoji` font's glyph bounding rect with a specified font size.

It may used to create custom emoji.

@param fontSizeThe specified font size.

@param imageScale图片宽高比

@return The font glyph bounding rect.

高度统一,宽度自由

@saylor--为了适应宽度自由的图片作为表情

*/

static inline CGRect YYEmojiGetGlyphBoundingLongRectWithFontSize(CGFloat fontSize,CGFloat imageScale){

CGRect rect;

rect.origin.x = 0;

rect.size.height = YYEmojiGetAscentWithFontSize(fontSize);

rect.size.width = rect.size.height * imageScale*0.75;

if(fontSize < 16){

rect.origin.y = -0.2525 * fontSize;

} else if(16 <= fontSize && fontSize <= 24){

rect.origin.y = 0.1225 * fontSize -6;

} else {

rect.origin.y = -0.1275 * fontSize;

}

return rect;

}

NSAttributedString+YYText.m

+(NSMutableAttributedString *)attachmentStringWithEmojiImage:(UIImage *)image

fontSize:(CGFloat)fontSize{

…

//原方法

//CGRect bounding1 = YYEmojiGetGlyphBoundingRectWithFontSize(fontSize);

//计算图片宽高比

CGFloat imageScale = image.size.width / image.size.height;

CGRect bounding = YYEmojiGetGlyphBoundingLongRectWithFontSize(fontSize,imageScale);

….

}

  • 添加IQKeyboard支持 YYTextview
    //添加IQKeyboard支持 YYTextView
    [[IQKeyboardManager sharedManager] registerTextFieldViewClass:[YYTextView class]
                                  didBeginEditingNotificationName:YYTextViewTextDidBeginEditingNotification
                                    didEndEditingNotificationName:YYTextViewTextDidEndEditingNotification];
    //默认关闭IQKeyboard 在需要的界面启用
    [IQKeyboardManager sharedManager].enable = NO;
    [[IQKeyboardManager sharedManager] setEnableAutoToolbar:NO];

YYLabel

以下问题的处理均在子类实现

  • 异步绘制,在列表刷新时YYLabel会有闪烁的问题。

  • 开启异步绘制的相关属性


self.displaysAsynchronously = YES;
//2018.01.04 注:忽略该句代码,否者变更字体、字号等属性不会触发UI更新。
//self.ignoreCommonProperties = YES;

self.fadeOnAsynchronouslyDisplay = NO;

self.fadeOnHighlight = NO;

//重写方法

-(void)setText:(NSString *)text {

  //用于处理异步绘制刷新闪烁的问题
  //strCache自行声明
  if([self.strCache isEqualToString:text]){
  return;
  //防止将内容置为nil
  if(text.length == 0){
    text = @"";
  }
  self.strCache = text;
  //[super setText:text];  //这里可以注释掉
  NSAttributedString *atrContent =[[NSAttributedString alloc]initWithString:text];
  [self fixLayoutSizeWithContent:atrContent];
}

//对于使用以下方式工作的朋友需要注意!!! 否则会引起刷新闪烁的问题
- (void)setAttributedText:(NSAttributedString *)attributedText {
    //用于处理 异步绘制 刷新闪烁的问题
    if ([self.atrCache isEqualToAttributedString:attributedText] || [self.atrCache.string isEqualToString:attributedText.string]) {
        return;
    }
    //防止将内容置为nil
    if (attributedText.length == 0) {
        attributedText = [[NSAttributedString alloc]initWithString:@""];
    }
    self.atrCache = attributedText;
    //使用富文本进行赋值时,所以需要禁用自定义的解析,否则解析代码会覆盖掉富文本的相关属性。如:字体、颜色等
    [self fixLayoutSizeWithContent:attributedText];  
}
  • iOS10和大屏6P会出现高度问题

-(void)fixLayoutSizeWithContent:(NSAttributedString *)strContent {
  CGFloat perfixLayoutWidth = self.preferredMaxLayoutWidth;//布局指定宽度
  //次要-Frame布局
  if(self.size.width && !perfixLayoutWidth){
      perfixLayoutWidth = self.size.width;
  }
  NSMutableAttributedString *text =[[NSMutableAttributedString alloc]initWithAttributedString:strContent];
  //这里注意要将原有的富文本布局属性持有
  text.alignment = self.textAlignment;
  text.font = self.font;
  text.textColor = self.textColor;

  NSRange selectedRange = text.rangeOfAll;
  //我这里有一个自定义的解析器
 //此处增加一个判断,主要是为了防止富文本赋值的情况下,解析会覆盖掉相关的属性。而且需要解析的场景,简单文本赋值应该都能处理了。!!! 控制属性,自行添加
  if(isEnableParser){
      [self.customTextParser parseText:text selectedRange:&selectedRange];
  }
  YYTextContainer *container =[YYTextContainer new];
  container.size = CGSizeMake(perfixLayoutWidth,HUGE);
  container.linePositionModifier = self.customTextModifier;
  container.maximumNumberOfRows = self.numberOfLines;
  container.truncationType = YYTextTruncationTypeEnd;
  YYTextLayout *textLayout =[YYTextLayout layoutWithContainer:container text:text];

  CGSize layoutSize = textLayout.textBoundingSize;
  //宽度修正
  if(layoutSize.width > perfixLayoutWidth){
    layoutSize.width = perfixLayoutWidth;
  }
  //这个方法参照YYKit Demo中结果高度始终有问题,所以未采用
  //CGFloat height =[self.customTextModifier heightForLineCount:textLayout.rowCount];
  //iOS 10高度修正,发现iOS10和大屏6P会出现高度问题,如果不修正一个奇怪的现象就是,YYLabel的高亮文本在点击时会有跳动。但YYTextView并没有发现这样的情况
  if((DP_IS_IOS10||DP_IS_IPHONE6PLUS)&& textLayout.rowCount > 1){
  //height += 4;
  layoutSize.height += 4;//这个值也是调来调去
  }
  //最奇葩的是这里赋值一定是这个顺序,如果顺序不对也是Bug多多
  self.size = layoutSize;
  self.textLayout = textLayout;
}

  • 配合AutoLayout:记得在赋值text后,更新Size约束
  • 更新

  • 搜狗输入法,全键盘模式下发现输入英文时,会在键盘的联想状态栏处出现连字情况。
  • 系统输入法,全键盘模式下发现点击联想栏出的单词输入时,单词会被空格打断。

系统输入法的问题,暂时还原。因为会引起其他问题...
问题修复,问题本质原因是替换文本完成后_selectedTextRange有些情况下没有得到更新。

问题跟踪

  • 搜狗输入法点击联想栏处输入单词的流程和系统是不同的,搜狗是先调用-(void)deleteBackward()方法,该方法会被调用多次删除之前输入的内容(上次输入的内容),然后再调用- (void)insertText:(NSString *)text方法插入联想词。
  • 系统输入法,不会走上述流程,只有一步调用- (void)replaceRange:(YYTextRange *)range withText:(NSString *)text来完成文本替换。
///其实以上问题的根本原因,基本上就是下面这几个代理方法的调用问题
@protocol UITextInputDelegate <NSObject>

- (void)selectionWillChange:(nullable id <UITextInput>)textInput;
- (void)selectionDidChange:(nullable id <UITextInput>)textInput;
- (void)textWillChange:(nullable id <UITextInput>)textInput;
- (void)textDidChange:(nullable id <UITextInput>)textInput;

@end

  • 跟着感觉走,修补的代码主要集中在以下两个方法:
  • (void)_replaceRange:(YYTextRange *)range withText:(NSString *)text notifyToDelegate:(BOOL)notify
  • (BOOL)_parseText
///处理后的代码
- (void)_replaceRange:(YYTextRange *)range withText:(NSString *)text notifyToDelegate:(BOOL)notify{
    if (_isExcludeNeed) {
        notify = NO;
    }

    if (NSEqualRanges(range.asRange, _selectedTextRange.asRange)) {
        //这里的代理方法需要注释掉
//        if (notify) [_inputDelegate selectionWillChange:self];
        NSRange newRange = NSMakeRange(0, 0);
        newRange.location = _selectedTextRange.start.offset + text.length;
        _selectedTextRange = [YYTextRange rangeWithRange:newRange];
//        if (notify) [_inputDelegate selectionDidChange:self];
    } else {
        if (range.asRange.length != text.length) {
            if (notify) [_inputDelegate selectionWillChange:self];
            NSRange unionRange = NSIntersectionRange(_selectedTextRange.asRange, range.asRange);
            if (unionRange.length == 0) {
                // no intersection
                if (range.end.offset <= _selectedTextRange.start.offset) {
                    NSInteger ofs = (NSInteger)text.length - (NSInteger)range.asRange.length;
                    NSRange newRange = _selectedTextRange.asRange;
                    newRange.location += ofs;
                    _selectedTextRange = [YYTextRange rangeWithRange:newRange];
                }
            } else if (unionRange.length == _selectedTextRange.asRange.length) {
                // target range contains selected range
                _selectedTextRange = [YYTextRange rangeWithRange:NSMakeRange(range.start.offset + text.length, 0)];
            } else if (range.start.offset >= _selectedTextRange.start.offset &&
                       range.end.offset <= _selectedTextRange.end.offset) {
                // target range inside selected range
                NSInteger ofs = (NSInteger)text.length - (NSInteger)range.asRange.length;
                NSRange newRange = _selectedTextRange.asRange;
                newRange.length += ofs;
                _selectedTextRange = [YYTextRange rangeWithRange:newRange];
            } else {
                // interleaving
                if (range.start.offset < _selectedTextRange.start.offset) {
                    NSRange newRange = _selectedTextRange.asRange;
                    newRange.location = range.start.offset + text.length;
                    newRange.length -= unionRange.length;
                    _selectedTextRange = [YYTextRange rangeWithRange:newRange];
                } else {
                    NSRange newRange = _selectedTextRange.asRange;
                    newRange.length -= unionRange.length;
                    _selectedTextRange = [YYTextRange rangeWithRange:newRange];
                }
            }
        
 _selectedTextRange = [self _correctedTextRange:_selectedTextRange];
            if (notify) [_inputDelegate selectionDidChange:self];
        }
    }

    //这里的代理方法 需要判断,如果设置了解析器则不执行,分析解析器方法中重复执行会有问题。
    if (!self.textParser) [_inputDelegate textWillChange:self];
    NSRange newRange = NSMakeRange(range.asRange.location, text.length);
    [_innerText replaceCharactersInRange:range.asRange withString:text];
    [_innerText removeDiscontinuousAttributesInRange:newRange];
    if (!self.textParser) [_inputDelegate textDidChange:self];

    /*
     修正光标位置的方法放在这里,因为此处已经替换文本完毕
     问题的本质原因,替换完文本后 range 没有得到更新
     */
//    NSLog(@"Correct cursor position");
    if (range.asRange.location + range.asRange.length == _selectedTextRange.asRange.location && _selectedTextRange.asRange.length == 0) {
        //修正_selectedTextRange
        [_inputDelegate selectionWillChange:self];
        
        _selectedTextRange = [YYTextRange rangeWithRange:NSMakeRange(_selectedTextRange.asRange.location + text.length - range.asRange.length, 0)];
        
        [_inputDelegate selectionDidChange:self];
    }



}

  • 解析方法
- (BOOL)_parseText {
    if (self.textParser) {
        YYTextRange *oldTextRange = _selectedTextRange;
        NSRange newRange = _selectedTextRange.asRange;
        
        //此处方法需要注释掉
//        if(!_isExcludeNeed)[_inputDelegate textWillChange:self];
        BOOL textChanged = [self.textParser parseText:_innerText selectedRange:&newRange];
//        if(!_isExcludeNeed)[_inputDelegate textDidChange:self];
        
        YYTextRange *newTextRange = [YYTextRange rangeWithRange:newRange];
        newTextRange = [self _correctedTextRange:newTextRange];
        
        if (![oldTextRange isEqual:newTextRange]) {
            [_inputDelegate selectionWillChange:self];
            _selectedTextRange = newTextRange;
            [_inputDelegate selectionDidChange:self];
        }
        return textChanged;
    }
    return NO;
}
  • 发现但没有解决掉的问题 往下看
1. 系统全键盘输入模式下,如果碰巧触发了自动纠正模式,此时如果点击键盘删除键,会执行以下流程: 
-[UIKeyboardlmpl deleteBackwardAndNotify:]
-[YYTextView setSelectedTextRange:]
...省略部分系统内部调用
-[UIKeyboardlmpl applyAutocorrection:]
-[YYTextView replaceRange:withText:]
...
-[YYTextView deleteBackward]
问题就出在`-[YYTextView replaceRange:withText:]`获得的text参数,传过来的竟然是联想框内高亮的候选词。真心不知道是怎么回事,如果有了解的兄弟希望能讲解下。
对比UITextView的表现来看,这一步完全是多余的。

2. 搜狗输入法全键盘模式下,输入英文字符后,点击联想框内的候选词发现覆盖现象,正确的表现应该是替换文本、清空联想框内的候选词,然后会追加一个空格。但事实上并不是这样的,也不知道是不是苹果有意的让第三方这样去运行。从相关的代理方法中,并没有找到引起该问题的实质原因。`Tip:系统输入法是会有一个追加空格的动作的,具体可以调试看`
代码执行流程:

- [UIKeyboadlmp deleteBackwardAndNotify:]
- [YYTextView deleteBackward]
- [YYTextView replaceRange:withText:]
- [YYTextView setSelectedTextRange:]
//这个会执行多次,每次只能删除一个字符
//删除后 再进行插入操作
...
- [UIKeyboardlmpl insertText:]
- [YYTextView insertText:]
- [YYTextView replaceRange:withText:]

关于上述问题的定位

-[YYTextView replaceRange:withText:] YYTextView.m:3541
-[UIKeyboardImpl applyAutocorrection:] 0x00000001077f78ca
-[UIKeyboardImpl acceptAutocorrection:executionContextPassingTIKeyboardCandidate:] 0x00000001077ed735
-[UIKeyboardImpl acceptAutocorrectionForWordTerminator:executionContextPassingTIKeyboardCandidate:] 0x00000001077ece54
__56-[UIKeyboardImpl acceptAutocorrectionForWordTerminator:]_block_invoke 0x00000001077ecc77
-[UIKeyboardTaskQueue continueExecutionOnMainThread] 0x000000010805c782
-[UIKeyboardTaskQueue performTaskOnMainThread:waitUntilDone:] 0x000000010805cbab
-[UIKeyboardImpl acceptAutocorrectionForWordTerminator:] 0x00000001077ecb87
-[UIKeyboardImpl acceptAutocorrection] 0x00000001077ef6d9
-[UIKeyboardImpl prepareForSelectionChange] 0x00000001077e5770
-[YYTextView setSelectedTextRange:] YYTextView.m:3377

哈 具体是哪里的问题,周一再分析~~~
更新解决方法如下:
从上面贴出来的调用栈来看,问题基本出在以下代码中。
-[YYTextView setSelectedTextRange:] YYTextView.m:3377
注释了以后,果然清爽了。

#pragma mark - @protocol UITextInput
- (void)setSelectedTextRange:(YYTextRange *)selectedTextRange {
    if (!selectedTextRange) return;
    selectedTextRange = [self _correctedTextRange:selectedTextRange];
    if ([selectedTextRange isEqual:_selectedTextRange]) return;
    [self _updateIfNeeded];
    [self _endTouchTracking];
    [self _hideMenu];
    _state.deleteConfirm = NO;
    _state.typingAttributesOnce = NO;
   //这里有问题 selectionWillChange 不明原因打断了deleteBackwardAndNotify 执行
//    [_inputDelegate selectionWillChange:self];
    _selectedTextRange = selectedTextRange;
    _lastTypeRange = _selectedTextRange.asRange;
//    [_inputDelegate selectionDidChange:self];
    
    [self _updateOuterProperties];
    [self _updateSelectionView];
    
    if (self.isFirstResponder) {
        [self _scrollRangeToVisible:_selectedTextRange];
    }
}

2017年09月04日 update


  • 竖版问题

    参考了Github上另外两人提交的代码
    @cszwdy
    @ smhjsw

    YYLabel.m 源文件做如下修改 参考链接

+ (YYTextLayout *)_shrinkLayoutWithLayout:(YYTextLayout *)layout {
    if (layout.text.length && layout.lines.count == 0) {
        YYTextContainer *container = layout.container.copy;
//        container.maximumNumberOfRows = 1;
        CGSize containerSize = container.size;
        if (!container.verticalForm) {
            containerSize.height = YYTextContainerMaxSize.height;
        } else {
            containerSize.width = YYTextContainerMaxSize.width;
        }
        container.size = containerSize;
        return [YYTextLayout layoutWithContainer:container text:layout.text];
    } else {
        return nil;
    }
}

YYTextLayout.m 源文件做如下修改 参考链接

//535行起
        if (constraintSizeIsExtended) {
            if (isVerticalForm) {
//                if (rect.origin.x + rect.size.width >
//                    constraintRectBeforeExtended.origin.x +
//                    constraintRectBeforeExtended.size.width) break;
                if (!CGRectIntersectsRect(rect, constraintRectBeforeExtended)) break;
                
            } else {
                if (rect.origin.y + rect.size.height >
                    constraintRectBeforeExtended.origin.y +
                    constraintRectBeforeExtended.size.height) break;
            }
        }

2018年01月09日 update


  • YYLabel textAlignment 问题

发现在使用textLayoutYYLabel进行完全控制布局时,如果赋空值则预先设置的textAlignment 将自动转换为NSTextAlignmentNatural

这里就直接上代码了:

//出现问题的代码 有两部分
//1. NSAttributedString+YYText.m
//text为空时,该宏的展开式并不会得到执行。在此情况下设置alignment是无意义的~~~
//结果就是_innerText.alignment 是默认值 NSTextAlignmentNatural
#define ParagraphStyleSet(_attr_) 

//2. YYLabel.m 
- (void)_updateOuterTextProperties {
    _text = [_innerText plainTextForRange:NSMakeRange(0, _innerText.length)];
    _font = _innerText.font;
    if (!_font) _font = [self _defaultFont];
    _textColor = _innerText.color;
    if (!_textColor) _textColor = [UIColor blackColor];
    
   //*******更改部分********
    //因为上面的问题,这里_innerText.alignment 是不能够采信的。
    BOOL isEmptyStr = _innerText.length == 0;
    if(!isEmptyStr)_textAlignment = _innerText.alignment;
    if(!isEmptyStr)_lineBreakMode = _innerText.lineBreakMode;
   //*******更改部分********

    NSShadow *shadow = _innerText.shadow;
    _shadowColor = shadow.shadowColor;
#if !TARGET_INTERFACE_BUILDER
    _shadowOffset = shadow.shadowOffset;
#else
    _shadowOffset = CGPointMake(shadow.shadowOffset.width, shadow.shadowOffset.height);
#endif
    
    _shadowBlurRadius = shadow.shadowBlurRadius;
    _attributedText = _innerText;
    [self _updateOuterLineBreakMode];
}

2018年02月05日 update


【残疾光标问题】 非YYKit 自身问题,权当自省了。

问题现象:YYTextView 使用时,苹方14号字体条件下,文本初始编辑状态,输入提示光标为正常的半高(残疾)。
提示:
不要随意更改原有逻辑!!!
遵循原有设计的默认值,如CoreText 默认字号为12,而我这里设置的解析器和行间距调整器的默认字号为14。
出现问题,先找自身原因。

- (void)setFont:(UIFont *)font {
   /*** 有问题的逻辑
    if ([self.customTextParser.font isEqual:font]) {
        return;
    }
    [super setFont:font];
    */
    
    /****改正后
    [super setFont:font];
    if ([self.customTextParser.font isEqual:font]) {
        return;
    }
    */

    self.customTextParser.font = font;
    self.customTextModifier.font = font;
    self.linePositionModifier = self.customTextModifier;
}

相关文章

  • YYKit之YYText、YYLabel使用总结(更新)

    1.索引 YYText YYLabel 更新 YYText IQKeyboardManager支持 布局问题 如果...

  • YYText源码分析

    YYText 简单介绍 YYText 是YYKit中的一个富文本显示,编辑组件,拥有YYLabel,YYText...

  • YYKit之YYText

    YYKit之YYText 转载链接: http://www.cnblogs.com/lujianwenance/p...

  • YYKit之YYLabel

    本文只对富文本中部分文字添加点击事件做简单介绍 1.添加点击事件 YYLabel中给部分文字添加点击事件主要是在富...

  • iOS CoreText(一)

    刚好最近项目中有用到CoreText,最近也看了看YYText中YYLabel的源码,总结一下 CoreText实...

  • iOS 文字横竖排切换

    使用YYText 的YYLabel 实现文字横竖排版时发现一个问题,当对verticalForm 设置为YES时,...

  • iOS - YYKit 之 YYText

    本文只是让自己加深下理解,方便以后查看,原作者看到有不合适的地方,或者大神们看到有不对的地方希望指正 ~ 原文地址...

  • YYKit之YYText阅读

    NSAttributedString (YYText) 检索字符的属性信息 获取字符属性来作为属性 获取段属性作为属性

  • YYText 源码解析 —— YYLabel (一)

    架构 (引用作者框架对比图片) YYText包括控件(YYLabel,YYTextView),布局(YYTextL...

  • YYText

    1.YYKit之YYText2.CoreText实现图文混排和点击事件3.认识 TextKit4.CoreText...

网友评论

  • 周大生_c1b6:博主你好,我想问下 我在tableView列表里面有用到YYLabel,在tableView reloadData的时候,这个label上的文字会闪烁,这是什么原因呢,其他的是UILabel,就不闪烁.
    Saylor_Lone:最近遇到过这个问题,但还没去深究。稍后弄明白,会更新到这篇文章里的。
  • Beyond无状态:请问博主 我设置textView.textVerticalAlignment = YYTextVerticalAlignmentCenter在模拟器上没问题,到真机上在中间行开始输入 咋回事啊
    Saylor_Lone:@多醋多辣 在横版布局的情况下,设置textView.textVerticalAlignment = YYTextVerticalAlignmentCenter 是会出现光标置中的问题,另外 self.automaticallyAdjustsScrollViewInsets = NO 这句代码 或者iOS11下的新API self.textView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever 在我这里并没有解决该问题。
    Beyond无状态:@NSaylor 刚刚解决了 加了一句self.automaticallyAdjustsScrollViewInsets = NO
    Saylor_Lone:没理解你的需求,贴张想要实现的效果图也好
  • 魔魔571:能否问下,能设置首行缩进吗
    魔魔571:@NSaylor 好的,谢谢
    Saylor_Lone:尝试了下可以的 和 UITextView一样的方式
    NSMutableAttributedString *text = [[NSMutableAttributedString alloc] initWithAttributedString:strContent];
    NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
    paragraphStyle.lineSpacing = 3; //行间距
    paragraphStyle.firstLineHeadIndent = 93.f; /**首行缩进宽度*/
    paragraphStyle.alignment = NSTextAlignmentJustified;
    NSDictionary *attributes = @{
    NSFontAttributeName:[UIFont systemFontOfSize:13],
    NSParagraphStyleAttributeName:paragraphStyle
    };
    [text setAttributes:attributes];
    label.attributedText = text;
  • lzp_John:请问下 我使用YYLabel 设置了行数为5,然后多出的部分用省略号和"全文"代替,但是设置label的高度的时候,我使用layout.textBoundingSize.height这个获取到的是整个label的高度,而不是折叠之后的label的高度,请问下这个怎么解决呢 ,就是获取折叠之后的label的高度
    lzp_John:@NSaylor 最后一行代码是添加了一个"全文" 的按钮,
    lzp_John:@NSaylor NSString *title =@"豫章故郡,洪都新府。星分翼轸,地接衡庐。襟三江而带五湖,控蛮荆而引瓯越。物华天宝,龙光射牛斗之墟;人杰地灵,徐孺下陈蕃之榻。雄州雾列,俊采星驰。台隍枕夷夏之交,宾主尽东南之美。都督阎公之雅望,棨戟遥临;宇文新州之懿范,襜帷暂驻。十旬休假,胜友如云;千里逢迎,高朋满座。腾蛟起凤,孟学士之词宗;紫电青霜,王将军之武库。家君作宰,路出名区;童子何知,躬逢胜饯。时维九月,序属三秋。潦水尽而寒潭清,烟光凝而暮山紫。俨骖騑于上路,访风景于崇阿。临帝子之长洲,得仙人之旧馆。层台耸翠,上出重霄;飞阁流丹,下临无地。鹤汀凫渚,穷岛屿之萦回;桂殿兰宫,列冈峦之体势。";
    NSMutableAttributedString *text = [[NSMutableAttributedString alloc]initWithString:title];
    text.yy_lineSpacing = 10;
    text.yy_font = [UIFont systemFontOfSize:17.0];
    CGSize size = CGSizeMake(ScreenW-20, CGFLOAT_MAX);
    YYTextLayout *layout = [YYTextLayout layoutWithContainerSize:size text:text];
    //添加文字cell的高度
    model.cellHeight += layout.textBoundingSize.height +10;
    self.contentLabel.userInteractionEnabled =YES;
    self.contentLabel.numberOfLines = 5;
    self.contentLabel.backgroundColor = [UIColor yellowColor];
    self.contentLabel.textVerticalAlignment =YYTextVerticalAlignmentTop;
    self.contentLabel.attributedText = text;
    self.contentLabel.frame = CGRectMake(0, 0, ScreenW - 20, layout.textBoundingSize.height);
    [self.certenView addSubview:self.contentLabel];
    [self addSeeMoreButton];
    Saylor_Lone:参考上文中 iOS10和大屏6P会出现高度问题 部分
    -(void)fixLayoutSizeWithContent:(NSAttributedString *)strContent
    该方法中的代码应该能解决你的问题
  • _码奴:YYLabel怎么实现多个点击事件,例如:文字的第3个到6个要点击跳转到某个界面,而第12个到18个文字点击要弹出对话框,这样多个点击事件怎么处理
    _码奴:@NSaylor 谢了,这个方法我也找到了,挺好使
    Saylor_Lone:YYLabel 子类构造方法
    - (instancetype)init {
    if (self = [super init]) {
    ....略
    @weakify(self)
    self.highlightTapAction = ^(UIView *containerView, NSAttributedString *text, NSRange range, CGRect rect) {
    @strongify(self)
    YYTextHighlight *highlight = [text attribute:YYTextHighlightAttributeName atIndex:range.location];

    NSDictionary *info = highlight.userInfo; ///这里的info 我是用解析器处理了,正则去做。如果你不想用解析器,那就自己处理下富文本 (YYKit的Demo 里面写的很详细,给富文本中想添加点击事件的字段添加 YYTextHighlight )
    [self highLightEvent:info];//事件处理
    };
    }

    return self;
    }

    example:
    #pragma mark - 点击事件处理
    - (void)highLightEvent:(NSDictionary *)info{

    if (info[@"label1"]) {
    NSString *strUserName = info[@"label1"];
    //跳转方法
    ....
    }

    if (info[@"label2"]) {
    NSString *strUrl = info[@"label2"];
    //弹出对话框
    ...
    }
    ///labelx 是你自定义的事件标签
    }

    ///手动处理富文本示例
    // 高亮状态的背景 (如果你需要的话)
    YYTextBorder *highlightBorder = [YYTextBorder new];
    highlightBorder.insets = UIEdgeInsetsMake(-2, 0, -2, 0);
    highlightBorder.cornerRadius = 3;
    highlightBorder.fillColor = _highlightBackgroundColor; //颜色自定义

    YYTextHighlight *highlight = [YYTextHighlight new];
    [highlight setBackgroundBorder:highlightBorder];
    highlight.userInfo = @{ @"lable1": @"传入你想传的内容" };
    [text setTextHighlight:highlight range:NSMakeRange(6,12 )];

    ///将处理好的富文本 回馈给YYLabel
    YYLabel *label = [YYLabel new];
    label.attributedText = text;
    ///end

本文标题:YYKit之YYText、YYLabel使用总结(更新)

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