Git Product home page Git Product logo

yytext's Introduction

YYText

License MIT  Carthage compatible  CocoaPods  CocoaPods  Support  Build Status

Powerful text framework for iOS to display and edit rich text.
(It's a component of YYKit)

Features

  • UILabel and UITextView API compatible
  • High performance asynchronous text layout and rendering
  • Extended CoreText attributes with more text effects
  • Text attachments with UIImage, UIView and CALayer
  • Custom highlight text range to allow user interact with
  • Text parser support (built in markdown/emoticon parser)
  • Text container path and exclusion paths support
  • Vertical form layout support (for CJK text)
  • Image and attributed text copy/paste support
  • Attributed text placeholder support
  • Custom keyboard view support
  • Undo and redo control
  • Attributed text archiver and unarchiver support
  • Multi-language and VoiceOver support
  • Interface Builder support
  • Fully documented

Architecture

YYText vs TextKit

Text Attributes

YYText supported attributes

Demo Attribute Name Class
TextAttachment YYTextAttachment
TextHighlight YYTextHighlight
TextBinding YYTextBinding
TextShadow
TextInnerShadow
YYTextShadow
TextBorder YYTextBorder
TextBackgroundBorder YYTextBorder
TextBlockBorder YYTextBorder
TextGlyphTransform NSValue(CGAffineTransform)
TextUnderline YYTextDecoration
TextStrickthrough YYTextDecoration
TextBackedString YYTextBackedString

CoreText attributes which is supported by YYText

Demo Attribute Name Class
Font UIFont(CTFontRef)
Kern NSNumber
StrokeWidth NSNumber
StrokeColor CGColorRef
Shadow NSShadow
Ligature NSNumber
VerticalGlyphForm NSNumber(BOOL)
WritingDirection NSArray(NSNumber)
RunDelegate CTRunDelegateRef
TextAlignment NSParagraphStyle
(NSTextAlignment)
LineBreakMode NSParagraphStyle
(NSLineBreakMode)
LineSpacing NSParagraphStyle
(CGFloat)
ParagraphSpacing
ParagraphSpacingBefore
NSParagraphStyle
(CGFloat)
FirstLineHeadIndent NSParagraphStyle
(CGFloat)
HeadIndent NSParagraphStyle
(CGFloat)
TailIndent NSParagraphStyle
(CGFloat)
MinimumLineHeight NSParagraphStyle
(CGFloat)
MaximumLineHeight NSParagraphStyle
(CGFloat)
LineHeightMultiple NSParagraphStyle
(CGFloat)
BaseWritingDirection NSParagraphStyle
(NSWritingDirection)
DefaultTabInterval
TabStops
NSParagraphStyle
CGFloat/NSArray(NSTextTab)

Usage

Basic

// YYLabel (similar to UILabel)
YYLabel *label = [YYLabel new];
label.frame = ...
label.font = ...
label.textColor = ...
label.textAlignment = ...
label.lineBreakMode = ...
label.numberOfLines = ...
label.text = ...
    
// YYTextView (similar to UITextView)
YYTextView *textView = [YYTextView new];
textView.frame = ...
textView.font = ...
textView.textColor = ...
textView.dataDetectorTypes = ...
textView.placeHolderText = ...
textView.placeHolderTextColor = ...
textView.delegate = ...

Attributed text

// 1. Create an attributed string.
NSMutableAttributedString *text = [[NSMutableAttributedString alloc] initWithString:@"Some Text, blabla..."];
    
// 2. Set attributes to text, you can use almost all CoreText attributes.
text.yy_font = [UIFont boldSystemFontOfSize:30];
text.yy_color = [UIColor blueColor];
[text yy_setColor:[UIColor redColor] range:NSMakeRange(0, 4)];
text.yy_lineSpacing = 10;
    
// 3. Set to YYLabel or YYTextView.
YYLabel *label = [YYLabel new];
label.frame = ...
label.attributedString = text;
    
YYTextView *textView = [YYTextView new];
textView.frame = ...
textView.attributedString = text;

Text highlight

You can use some convenience methods to set text highlight:

[text yy_setTextHighlightRange:range
                       color:[UIColor blueColor]
             backgroundColor:[UIColor grayColor]
                   tapAction:^(UIView *containerView, NSAttributedString *text, NSRange range, CGRect rect){ 
                       NSLog(@"tap text range:..."); 
                   }];

Or set the text highlight with your custom config:

// 1. Create a 'highlight' attribute for text.
YYTextBorder *border = [YYTextBorder borderWithFillColor:[UIColor grayColor] cornerRadius:3];
   
YYTextHighlight *highlight = [YYTextHighlight new];
[highlight setColor:[UIColor whiteColor]];
[highlight setBackgroundBorder:highlightBorder];
highlight.tapAction = ^(UIView *containerView, NSAttributedString *text, NSRange range, CGRect rect) {
 NSLog(@"tap text range:..."); 
 // you can also set the action handler to YYLabel or YYTextView.
};
    
// 2. Add 'highlight' attribute to a range of text.
[attributedText yy_setTextHighlight:highlight range:highlightRange];
    
// 3. Set text to label or text view.
YYLabel *label = ...
label.attributedText = attributedText
    
YYTextView *textView = ...
textView.attributedText = ...
    
// 4. Receive user interactive action.
label.highlightTapAction = ^(UIView *containerView, NSAttributedString *text, NSRange range, CGRect rect) {
   NSLog(@"tap text range:...");
};
label.highlightLongPressAction = ^(UIView *containerView, NSAttributedString *text, NSRange range, CGRect rect) {
   NSLog(@"long press text range:...");
};
    
@UITextViewDelegate
- (void)textView:(YYTextView *)textView didTapHighlight:(YYTextHighlight *)highlight inRange:(NSRange)characterRange rect:(CGRect)rect {
   NSLog(@"tap text range:...");
}
- (void)textView:(YYTextView *)textView didLongPressHighlight:(YYTextHighlight *)highlight inRange:(NSRange)characterRange rect:(CGRect)rect {
   NSLog(@"long press text range:...");
}

Text attachments

NSMutableAttributedString *text = [NSMutableAttributedString new];
UIFont *font = [UIFont systemFontOfSize:16];
NSMutableAttributedString *attachment = nil;
	
// UIImage attachment
UIImage *image = [UIImage imageNamed:@"dribbble64_imageio"];
attachment = [NSMutableAttributedString yy_attachmentStringWithContent:image contentMode:UIViewContentModeCenter attachmentSize:image.size alignToFont:font alignment:YYTextVerticalAlignmentCenter];
[text appendAttributedString: attachment];
	
// UIView attachment
UISwitch *switcher = [UISwitch new];
[switcher sizeToFit];
attachment = [NSMutableAttributedString yy_attachmentStringWithContent:switcher contentMode:UIViewContentModeBottom attachmentSize:switcher.size alignToFont:font alignment:YYTextVerticalAlignmentCenter];
[text appendAttributedString: attachment];
	
// CALayer attachment
CASharpLayer *layer = [CASharpLayer layer];
layer.path = ...
attachment = [NSMutableAttributedString yy_attachmentStringWithContent:layer contentMode:UIViewContentModeBottom attachmentSize:switcher.size alignToFont:font alignment:YYTextVerticalAlignmentCenter];
[text appendAttributedString: attachment];

Text layout calculation

NSAttributedString *text = ...
CGSize size = CGSizeMake(100, CGFLOAT_MAX);
YYTextLayout *layout = [YYTextLayout layoutWithContainerSize:size text:text];
	
// get text bounding
layout.textBoundingRect; // get bounding rect
layout.textBoundingSize; // get bounding size
	
 // query text layout
[layout lineIndexForPoint:CGPointMake(10,10)];
[layout closestLineIndexForPoint:CGPointMake(10,10)];
[layout closestPositionToPoint:CGPointMake(10,10)];
[layout textRangeAtPoint:CGPointMake(10,10)];
[layout rectForRange:[YYTextRange rangeWithRange:NSMakeRange(10,2)]];
[layout selectionRectsForRange:[YYTextRange rangeWithRange:NSMakeRange(10,2)]];
	
// text layout display
YYLabel *label = [YYLabel new];
label.size = layout.textBoundingSize;
label.textLayout = layout;

Adjust text line position

// Convenience methods:
// 1. Create a text line position modifier, implements `YYTextLinePositionModifier` protocol.
// 2. Set it to label or text view.
	
YYTextLinePositionSimpleModifier *modifier = [YYTextLinePositionSimpleModifier new];
modifier.fixedLineHeight = 24;
	
YYLabel *label = [YYLabel new];
label.linePositionModifier = modifier;
	
// Fully control
YYTextLinePositionSimpleModifier *modifier = [YYTextLinePositionSimpleModifier new];
modifier.fixedLineHeight = 24;
	
YYTextContainer *container = [YYTextContainer new];
container.size = CGSizeMake(100, CGFLOAT_MAX);
container.linePositionModifier = modifier;
	
YYTextLayout *layout = [YYTextLayout layoutWithContainer:container text:text];
YYLabel *label = [YYLabel new];
label.size = layout.textBoundingSize;
label.textLayout = layout;

Asynchronous layout and rendering

// If you have performance issues,
// you may enable the asynchronous display mode.
YYLabel *label = ...
label.displaysAsynchronously = YES;
    
// If you want to get the highest performance, you should do 
// text layout with `YYTextLayout` class in background thread.
YYLabel *label = [YYLabel new];
label.displaysAsynchronously = YES;
label.ignoreCommonProperties = YES;
    
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
   // Create attributed string.
   NSMutableAttributedString *text = [[NSMutableAttributedString alloc] initWithString:@"Some Text"];
   text.yy_font = [UIFont systemFontOfSize:16];
   text.yy_color = [UIColor grayColor];
   [text yy_setColor:[UIColor redColor] range:NSMakeRange(0, 4)];
 	
   // Create text container
   YYTextContainer *container = [YYTextContainer new];
   container.size = CGSizeMake(100, CGFLOAT_MAX);
   container.maximumNumberOfRows = 0;
   
   // Generate a text layout.
   YYTextLayout *layout = [YYTextLayout layoutWithContainer:container text:text];
   
   dispatch_async(dispatch_get_main_queue(), ^{
       label.size = layout.textBoundingSize;
       label.textLayout = layout;
   });
});

Text container control

YYLabel *label = ...
label.textContainerPath = [UIBezierPath bezierPathWith...];
label.exclusionPaths = 	@[[UIBezierPath bezierPathWith...];,...];
label.textContainerInset = UIEdgeInsetsMake(...);
label.verticalForm = YES/NO;
    
YYTextView *textView = ...
textView.exclusionPaths = 	@[[UIBezierPath bezierPathWith...];,...];
textView.textContainerInset = UIEdgeInsetsMake(...);
textView.verticalForm = YES/NO;

Text parser

// 1. Create a text parser
	
YYTextSimpleEmoticonParser *parser = [YYTextSimpleEmoticonParser new];
NSMutableDictionary *mapper = [NSMutableDictionary new];
mapper[@":smile:"] = [UIImage imageNamed:@"smile.png"];
mapper[@":cool:"] = [UIImage imageNamed:@"cool.png"];
mapper[@":cry:"] = [UIImage imageNamed:@"cry.png"];
mapper[@":wink:"] = [UIImage imageNamed:@"wink.png"];
parser.emoticonMapper = mapper;
	
YYTextSimpleMarkdownParser *parser = [YYTextSimpleMarkdownParser new];
[parser setColorWithDarkTheme];
    
MyCustomParser *parser = ... // custom parser
    
// 2. Attach parser to label or text view
YYLabel *label = ...
label.textParser = parser;
    
YYTextView *textView = ...
textView.textParser = parser;

Debug

// Set a shared debug option to show text layout result.
YYTextDebugOption *debugOptions = [YYTextDebugOption new];
debugOptions.baselineColor = [UIColor redColor];
debugOptions.CTFrameBorderColor = [UIColor redColor];
debugOptions.CTLineFillColor = [UIColor colorWithRed:0.000 green:0.463 blue:1.000 alpha:0.180];
debugOptions.CGGlyphBorderColor = [UIColor colorWithRed:1.000 green:0.524 blue:0.000 alpha:0.200];
[YYTextDebugOption setSharedDebugOption:debugOptions];

More examples

See Demo/YYTextDemo.xcodeproj for more examples:



Installation

CocoaPods

  1. Add pod 'YYText' to your Podfile.
  2. Run pod install or pod update.
  3. Import <YYText/YYText.h>.

Carthage

  1. Add github "ibireme/YYText" to your Cartfile.
  2. Run carthage update --platform ios and add the framework to your project.
  3. Import <YYText/YYText.h>.

Manually

  1. Download all the files in the YYText subdirectory.
  2. Add the source files to your Xcode project.
  3. Link with required frameworks:
    • UIKit
    • CoreFoundation
    • CoreText
    • QuartzCore
    • Accelerate
    • MobileCoreServices
  4. Import YYText.h.

Notice

You may add YYImage or YYWebImage to your project if you want to support animated image (GIF/APNG/WebP).

Documentation

Full API documentation is available on CocoaDocs.
You can also install documentation locally using appledoc.

Requirements

This library requires iOS 6.0+ and Xcode 8.0+.

License

YYText is released under the MIT license. See LICENSE file for details.



中文介绍

功能强大的 iOS 富文本编辑与显示框架。
(该项目是 YYKit 组件之一)

特性

  • API 兼容 UILabel 和 UITextView
  • 支持高性能的异步排版和渲染
  • 扩展了 CoreText 的属性以支持更多文字效果
  • 支持 UIImage、UIView、CALayer 作为图文混排元素
  • 支持添加自定义样式的、可点击的文本高亮范围
  • 支持自定义文本解析 (内置简单的 Markdown/表情解析)
  • 支持文本容器路径、内部留空路径的控制
  • 支持文字竖排版,可用于编辑和显示中日韩文本
  • 支持图片和富文本的复制粘贴
  • 文本编辑时,支持富文本占位符
  • 支持自定义键盘视图
  • 撤销和重做次数的控制
  • 富文本的序列化与反序列化支持
  • 支持多语言,支持 VoiceOver
  • 支持 Interface Builder
  • 全部代码都有文档注释

架构

YYText 和 TextKit 架构对比

文本属性

YYText 原生支持的属性

Demo Attribute Name Class
TextAttachment YYTextAttachment
TextHighlight YYTextHighlight
TextBinding YYTextBinding
TextShadow
TextInnerShadow
YYTextShadow
TextBorder YYTextBorder
TextBackgroundBorder YYTextBorder
TextBlockBorder YYTextBorder
TextGlyphTransform NSValue(CGAffineTransform)
TextUnderline YYTextDecoration
TextStrickthrough YYTextDecoration
TextBackedString YYTextBackedString

YYText 支持的 CoreText 属性

Demo Attribute Name Class
Font UIFont(CTFontRef)
Kern NSNumber
StrokeWidth NSNumber
StrokeColor CGColorRef
Shadow NSShadow
Ligature NSNumber
VerticalGlyphForm NSNumber(BOOL)
WritingDirection NSArray(NSNumber)
RunDelegate CTRunDelegateRef
TextAlignment NSParagraphStyle
(NSTextAlignment)
LineBreakMode NSParagraphStyle
(NSLineBreakMode)
LineSpacing NSParagraphStyle
(CGFloat)
ParagraphSpacing
ParagraphSpacingBefore
NSParagraphStyle
(CGFloat)
FirstLineHeadIndent NSParagraphStyle
(CGFloat)
HeadIndent NSParagraphStyle
(CGFloat)
TailIndent NSParagraphStyle
(CGFloat)
MinimumLineHeight NSParagraphStyle
(CGFloat)
MaximumLineHeight NSParagraphStyle
(CGFloat)
LineHeightMultiple NSParagraphStyle
(CGFloat)
BaseWritingDirection NSParagraphStyle
(NSWritingDirection)
DefaultTabInterval
TabStops
NSParagraphStyle
CGFloat/NSArray(NSTextTab)

用法

基本用法

// YYLabel (和 UILabel 用法一致)
YYLabel *label = [YYLabel new];
label.frame = ...
label.font = ...
label.textColor = ...
label.textAlignment = ...
label.lineBreakMode = ...
label.numberOfLines = ...
label.text = ...
    
// YYTextView (和 UITextView 用法一致)
YYTextView *textView = [YYTextView new];
textView.frame = ...
textView.font = ...
textView.textColor = ...
textView.dataDetectorTypes = ...
textView.placeHolderText = ...
textView.placeHolderTextColor = ...
textView.delegate = ...

属性文本

// 1. 创建一个属性文本
NSMutableAttributedString *text = [[NSMutableAttributedString alloc] initWithString:@"Some Text, blabla..."];
    
// 2. 为文本设置属性
text.yy_font = [UIFont boldSystemFontOfSize:30];
text.yy_color = [UIColor blueColor];
[text yy_setColor:[UIColor redColor] range:NSMakeRange(0, 4)];
text.yy_lineSpacing = 10;
    
// 3. 赋值到 YYLabel 或 YYTextView
YYLabel *label = [YYLabel new];
label.frame = ...
label.attributedString = text;
    
YYTextView *textView = [YYTextView new];
textView.frame = ...
textView.attributedString = text;

文本高亮

你可以用一些已经封装好的简便方法来设置文本高亮:

[text yy_setTextHighlightRange:range
                       color:[UIColor blueColor]
             backgroundColor:[UIColor grayColor]
                   tapAction:^(UIView *containerView, NSAttributedString *text, NSRange range, CGRect rect){ 
                       NSLog(@"tap text range:..."); 
                   }];

或者用更复杂的办法来调节文本高亮的细节:

// 1. 创建一个"高亮"属性,当用户点击了高亮区域的文本时,"高亮"属性会替换掉原本的属性
YYTextBorder *border = [YYTextBorder borderWithFillColor:[UIColor grayColor] cornerRadius:3];
   
YYTextHighlight *highlight = [YYTextHighlight new];
[highlight setColor:[UIColor whiteColor]];
[highlight setBackgroundBorder:highlightBorder];
highlight.tapAction = ^(UIView *containerView, NSAttributedString *text, NSRange range, CGRect rect) {
 NSLog(@"tap text range:..."); 
 // 你也可以把事件回调放到 YYLabel 和 YYTextView 来处理。
};
    
// 2. 把"高亮"属性设置到某个文本范围
[attributedText yy_setTextHighlight:highlight range:highlightRange];
    
// 3. 把属性文本设置到 YYLabel 或 YYTextView
YYLabel *label = ...
label.attributedText = attributedText
    
YYTextView *textView = ...
textView.attributedText = ...
    
// 4. 接受事件回调
label.highlightTapAction = ^(UIView *containerView, NSAttributedString *text, NSRange range, CGRect rect) {
   NSLog(@"tap text range:...");
};
label.highlightLongPressAction = ^(UIView *containerView, NSAttributedString *text, NSRange range, CGRect rect) {
   NSLog(@"long press text range:...");
};
    
@UITextViewDelegate
- (void)textView:(YYTextView *)textView didTapHighlight:(YYTextHighlight *)highlight inRange:(NSRange)characterRange rect:(CGRect)rect {
   NSLog(@"tap text range:...");
}
- (void)textView:(YYTextView *)textView didLongPressHighlight:(YYTextHighlight *)highlight inRange:(NSRange)characterRange rect:(CGRect)rect {
   NSLog(@"long press text range:...");
}

图文混排

NSMutableAttributedString *text = [NSMutableAttributedString new];
UIFont *font = [UIFont systemFontOfSize:16];
NSMutableAttributedString *attachment = nil;
	
// 嵌入 UIImage
UIImage *image = [UIImage imageNamed:@"dribbble64_imageio"];
attachment = [NSMutableAttributedString yy_attachmentStringWithContent:image contentMode:UIViewContentModeCenter attachmentSize:image.size alignToFont:font alignment:YYTextVerticalAlignmentCenter];
[text appendAttributedString: attachment];
	
// 嵌入 UIView
UISwitch *switcher = [UISwitch new];
[switcher sizeToFit];
attachment = [NSMutableAttributedString yy_attachmentStringWithContent:switcher contentMode:UIViewContentModeBottom attachmentSize:switcher.size alignToFont:font alignment:YYTextVerticalAlignmentCenter];
[text appendAttributedString: attachment];
	
// 嵌入 CALayer
CASharpLayer *layer = [CASharpLayer layer];
layer.path = ...
attachment = [NSMutableAttributedString yy_attachmentStringWithContent:layer contentMode:UIViewContentModeBottom attachmentSize:switcher.size alignToFont:font alignment:YYTextVerticalAlignmentCenter];
[text appendAttributedString: attachment];

文本布局计算

NSAttributedString *text = ...
CGSize size = CGSizeMake(100, CGFLOAT_MAX);
YYTextLayout *layout = [YYTextLayout layoutWithContainerSize:size text:text];
	
// 获取文本显示位置和大小
layout.textBoundingRect; // get bounding rect
layout.textBoundingSize; // get bounding size
	
 // 查询文本排版结果
[layout lineIndexForPoint:CGPointMake(10,10)];
[layout closestLineIndexForPoint:CGPointMake(10,10)];
[layout closestPositionToPoint:CGPointMake(10,10)];
[layout textRangeAtPoint:CGPointMake(10,10)];
[layout rectForRange:[YYTextRange rangeWithRange:NSMakeRange(10,2)]];
[layout selectionRectsForRange:[YYTextRange rangeWithRange:NSMakeRange(10,2)]];
	
// 显示文本排版结果
YYLabel *label = [YYLabel new];
label.size = layout.textBoundingSize;
label.textLayout = layout;

文本行位置调整

// 由于中文、英文、Emoji 等字体高度不一致,或者富文本中出现了不同字号的字体,
// 可能会造成每行文字的高度不一致。这里可以添加一个修改器来实现固定行高,或者自定义文本行位置。
  
// 简单的方法:
// 1. 创建一个文本行位置修改类,实现 `YYTextLinePositionModifier` 协议。
// 2. 设置到 Label 或 TextView。
	
YYTextLinePositionSimpleModifier *modifier = [YYTextLinePositionSimpleModifier new];
modifier.fixedLineHeight = 24;
	
YYLabel *label = [YYLabel new];
label.linePositionModifier = modifier;
	
// 完全控制:
YYTextLinePositionSimpleModifier *modifier = [YYTextLinePositionSimpleModifier new];
modifier.fixedLineHeight = 24;
	
YYTextContainer *container = [YYTextContainer new];
container.size = CGSizeMake(100, CGFLOAT_MAX);
container.linePositionModifier = modifier;
	
YYTextLayout *layout = [YYTextLayout layoutWithContainer:container text:text];
YYLabel *label = [YYLabel new];
label.size = layout.textBoundingSize;
label.textLayout = layout;

异步排版和渲染

// 如果你在显示字符串时有性能问题,可以这样开启异步模式:
YYLabel *label = ...
label.displaysAsynchronously = YES;
    
// 如果需要获得最高的性能,你可以在后台线程用 `YYTextLayout` 进行预排版: 
YYLabel *label = [YYLabel new];
label.displaysAsynchronously = YES; //开启异步绘制
label.ignoreCommonProperties = YES; //忽略除了 textLayout 之外的其他属性
    
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
   // 创建属性字符串
   NSMutableAttributedString *text = [[NSMutableAttributedString alloc] initWithString:@"Some Text"];
   text.yy_font = [UIFont systemFontOfSize:16];
   text.yy_color = [UIColor grayColor];
   [text yy_setColor:[UIColor redColor] range:NSMakeRange(0, 4)];
 
   // 创建文本容器
   YYTextContainer *container = [YYTextContainer new];
   container.size = CGSizeMake(100, CGFLOAT_MAX);
   container.maximumNumberOfRows = 0;
   
   // 生成排版结果
   YYTextLayout *layout = [YYTextLayout layoutWithContainer:container text:text];
   
   dispatch_async(dispatch_get_main_queue(), ^{
       label.size = layout.textBoundingSize;
       label.textLayout = layout;
   });
});

文本容器控制

YYLabel *label = ...
label.textContainerPath = [UIBezierPath bezierPathWith...];
label.exclusionPaths = 	@[[UIBezierPath bezierPathWith...];,...];
label.textContainerInset = UIEdgeInsetsMake(...);
label.verticalForm = YES/NO;
    
YYTextView *textView = ...
textView.exclusionPaths = 	@[[UIBezierPath bezierPathWith...];,...];
textView.textContainerInset = UIEdgeInsetsMake(...);
textView.verticalForm = YES/NO;

文本解析

// 1. 创建一个解析器
	
// 内置简单的表情解析
YYTextSimpleEmoticonParser *parser = [YYTextSimpleEmoticonParser new];
NSMutableDictionary *mapper = [NSMutableDictionary new];
mapper[@":smile:"] = [UIImage imageNamed:@"smile.png"];
mapper[@":cool:"] = [UIImage imageNamed:@"cool.png"];
mapper[@":cry:"] = [UIImage imageNamed:@"cry.png"];
mapper[@":wink:"] = [UIImage imageNamed:@"wink.png"];
parser.emoticonMapper = mapper;
	
// 内置简单的 markdown 解析
YYTextSimpleMarkdownParser *parser = [YYTextSimpleMarkdownParser new];
[parser setColorWithDarkTheme];
    
// 实现 `YYTextParser` 协议的自定义解析器
MyCustomParser *parser = ... 
    
// 2. 把解析器添加到 YYLabel 或 YYTextView
YYLabel *label = ...
label.textParser = parser;
    
YYTextView *textView = ...
textView.textParser = parser;

Debug

// 设置一个全局的 debug option 来显示排版结果。
YYTextDebugOption *debugOptions = [YYTextDebugOption new];
debugOptions.baselineColor = [UIColor redColor];
debugOptions.CTFrameBorderColor = [UIColor redColor];
debugOptions.CTLineFillColor = [UIColor colorWithRed:0.000 green:0.463 blue:1.000 alpha:0.180];
debugOptions.CGGlyphBorderColor = [UIColor colorWithRed:1.000 green:0.524 blue:0.000 alpha:0.200];
[YYTextDebugOption setSharedDebugOption:debugOptions];

更多示例

查看演示工程 Demo/YYTextDemo.xcodeproj:



安装

CocoaPods

  1. 在 Podfile 中添加 pod 'YYText'
  2. 执行 pod installpod update
  3. 导入 <YYText/YYText.h>。

Carthage

  1. 在 Cartfile 中添加 github "ibireme/YYText"
  2. 执行 carthage update --platform ios 并将生成的 framework 添加到你的工程。
  3. 导入 <YYText/YYText.h>。

手动安装

  1. 下载 YYText 文件夹内的所有内容。
  2. 将 YYText 内的源文件添加(拖放)到你的工程。
  3. 链接以下 frameworks:
    • UIKit
    • CoreFoundation
    • CoreText
    • QuartzCore
    • Accelerate
    • MobileCoreServices
  4. 导入 YYText.h

注意

你可以添加 YYImageYYWebImage 到你的工程,以支持动画格式(GIF/APNG/WebP)的图片。

文档

你可以在 CocoaDocs 查看在线 API 文档,也可以用 appledoc 本地生成文档。

系统要求

该项目最低支持 iOS 6.0Xcode 8.0

已知问题

  • YYText 并不能支持所有 CoreText/TextKit 的属性,比如 NSBackgroundColor、NSStrikethrough、NSUnderline、NSAttachment、NSLink 等,但 YYText 中基本都有对应属性作为替代。详情见上方表格。
  • YYTextView 未实现局部刷新,所以在输入和编辑大量的文本(比如超过大概五千个汉字、或大概一万个英文字符)时会出现较明显的卡顿现象。
  • 竖排版时,添加 exclusionPaths 在少数情况下可能会导致文本显示空白。
  • 当添加了非矩形的 textContainerPath,并且有嵌入大于文本排版方向宽度的 RunDelegate 时,RunDelegate 之后的文字会无法显示。这是 CoreText 的 Bug(或者说是 Feature)。

许可证

YYText 使用 MIT 许可证,详情见 LICENSE 文件。

yytext's People

Contributors

100mango avatar codeeagle avatar devjiangzhou avatar euanchan avatar ibireme avatar mariotaku avatar michaelhuyp avatar poboke avatar pylam avatar willbin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

yytext's Issues

selectedRange不准确

您好。在这个代理方法里面- (void)textViewDidChangeSelection:(YYTextView *)textView,返回回来的selectedRange不准确,具体的说是长按后处于选定状态下,返回的range.length为0,但是按一下空白区域,让蓝色选定状态消失,这次返回的range的结果是正确的,length为选定的文本的长度。

刚刚又试了一下,这个range始终返回的是上一次操作的range

Found a weird performance of YYTextView when it's contentEdge was (0, 0, 0, 0)

Simply creat a YYTextView:

    self.automaticallyAdjustsScrollViewInsets = NO;
    YYTextView *textView = [[YYTextView alloc]initWithFrame:CGRectMake(0, 20, self.view.width, 100)];
    textView.backgroundColor = [UIColor colorWithWhite:0.5 alpha:0.5];
    textView.text = @"This is test text";
    textView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
    [self.view addSubview:textView];

Run app and it looks like:
Uploading 2.png…
Uploading 2.png…

(Sorry failed to upload a screenShot, the text ("this is a test text") can't be seen in textView, and after I type some word, still nothing can be seen including the cursor)

Then I change edgeInset.top to 0.5 and run agin, YYTextView look normal, it also look fine when edgeInset.top was -0.5.
But when edgeInset.top was 0, seems everything just went wrong.
I found you asways set the contentEdge to (64, 0 , 0 , 0) in the Demo, was the contentEdge's top just can't be 0? Or am I miss something?

请问两个问题

1、插入图片后,字体会变的很小,好像是一个默认字体。
2、如何获取我插入的附件数组?比如我要输入很多文字,很多图片,最后我要做一个“提交文章”的功能,这些图片我要上传到服务器上。
3、输入很多文字的时候,内存还是会变得很大,有被系统杀掉的风险。

YYLabel使用问题

使用new / alloc] init] 创建对象,再设置frame属性, YYLabel显示
而直接使用 alloc] initWithFrame 创建对象, YYLabel无法显示

当文本含有表情时,YYTextLayout计算出来的高度是不正确的

应该是把表情符号当做文本处理后进行高度计算了,
如文本:您haidf阿打发士大夫撒地方发的啥方[f024t]法发达范德萨法撒旦法地方
[f024t] 代表一个表情

NSMutableAttributedString *text = [[NSMutableAttributedString alloc]initWithString:txt];
text.yy_font=[UIFont systemFontOfSize:17.0f];

YYTextLinePositionSimpleModifier *modifier = [YYTextLinePositionSimpleModifier new];
modifier.fixedLineHeight = 22.0f;

YYTextContainer *container = [YYTextContainer new];
container.size =  CGSizeMake([[UIScreen mainScreen] bounds].size.width * 0.7f-50, CGFLOAT_MAX);
container.linePositionModifier = modifier;

YYTextLayout *layout = [YYTextLayout layoutWithContainer:container text:text ];

实质显示只有3行,计算出来是4行。屏幕宽度320

在TableViewCell中添加 YYAnimatedImageView 上下滚动时,有时图标会不显示

添加的代码如下:

    YYImage *image = [YYImage imageNamed:imageName];
    YYAnimatedImageView *imageView = [[YYAnimatedImageView alloc] initWithImage:image];

    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(5, 2, 38, 16)];
    label.text = text;
    label.font = [UIFont systemFontOfSize:12];
    label.textColor = color;
    [imageView addSubview:label];

    NSMutableAttributedString *imgText = [NSMutableAttributedString yy_attachmentStringWithContent:imageView contentMode:UIViewContentModeCenter attachmentSize:size alignToFont:[UIFont systemFontOfSize:12] alignment:YYTextVerticalAlignmentBottom];

    [_attrText appendAttributedString:imgText];

YYTextView 问题

编辑过程中, 会遇到下面Crash.
Terminating app due to uncaught exception 'NSRangeException', reason: 'NSMutableRLEArray objectAtIndex:effectiveRange:: Out of bounds'
Code:
- (NSDictionary *)attributesAtIndex:(NSUInteger)index { if (self.length > 0 && index == self.length) index--; return [self attributesAtIndex:index effectiveRange:NULL]; }

正则表达式匹配有bug

如果text是预先赋值进入的,那渲染就没有问题

但是在后续手动输入一个匹配项之后,所有的字符都被认为是匹配的

好像是effectiveRange取区间有问题

e4bd1e10-65d2-4435-a36b-3e9bcbeb313e

How to interact with the custom `UIView` attachment?

Thanks for this great library! In the README example, I found the following codes:

// UIView attachment
UISwitch *switcher = [UISwitch new];
[switcher sizeToFit];
attachment = [NSMutableAttributedString yy_attachmentStringWithContent:switcher contentMode:UIViewContentModeBottom attachmentSize:switcher.frame.size alignToFont:font alignment:YYTextVerticalAlignmentCenter];
[text appendAttributedString: attachment];

However, the UISwitch is not selectable. How to enable selection of the UISwitch (or other element like UITextField)?

use cocoapods build error

pod 'YYWebImage'
pod 'YYKit'
pod 'YYText'

build error :
1.Redefinition of 'YYTextVerticalAlignment'
2.Duplicate interface definition for class 'YYTextRunDelegate'
3.Duplicate interface definition for class 'YYAnimatedImageView'

关于基本UILable的用法

我的cell并不是需要大量富文本,所以我就直接用YYLbel的基本用法,只是让它异步绘制。代码如下
_requir=[YYLabel new];
_requir.displaysAsynchronously=YES;
_requir.frame=CGRectMake(110, 35, 120, 14);
_requir.backgroundColor=[UIColor redColor];
[self.contentView addSubview:_requir];
_requir.font=kSystemFont(14);

    _stock=[[YYLabel alloc]init];
    _stock.displaysAsynchronously=YES;
    _stock.backgroundColor=[UIColor redColor];
    _stock.frame=CGRectMake(110, 60, 120, 14);
    [self.contentView addSubview:_stock];
    _stock.font=kSystemFont(14);

然后我在setModel的方法里
_requir.text=[NSString stringWithFormat:@"兑换条件:%@",model.convertCondition];
_stock.text=[NSString stringWithFormat:@"剩余:%d份",(int)model.residueNumber];

但是结果却是
img_0252

只有把_stock的高加3也就是17才能显示出来。这是什么情况,我有点摸不着头脑。希望表达清楚了,望解答。

如何优雅的添加多个textparse

目前好像只能拥有一个textparse
这样的话就需要将许多不同的解析内容全部写到一起,比如:一个textview需要解析自定义emoji也需要解析@xxx
能不能自己写了一个@xxx解析然和与原来的YYTextSimpleEmoticonParser进行合并使用呢?

你好,引用报错问题。

你好,我在使用你的YYText框架练习的时候,当我模仿YYTextDemo里边的YYTextAttachmentExample,有qq几个动画,他们使用的是YYImage,每次我引用YYImage,就报错。找不到什么问题,没有重复的YYImageCoder文件名,这文件也没有被链接2次。把YYImage删除后又添加还是不行。Other Linker Flags下边什么都没有。另外这种报错每次遇到都很麻烦,不知道您怎么解决的呢?我只知道看看有没文件名重复,build Phases有没有链接重复,别的都不确定
日志:
Undefined symbols for architecture x86_64:
"_crc32", referenced from:
_yy_png_copy_frame_data_at_index in YYImageCoder.o
-[YYImageEncoder _encodeAPNG] in YYImageCoder.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

YYLabel显示不出的问题

我使用的Masonry布局,在ios8.4下遇到了如下问题
1.当要显示的字体较大时超过了要显示的范围,YYLabel什么都不显示
2.当添加了文本解析器后,必须减小字体,文字和表情才能显示出来
image
没有使用表情解析时能够显示出来
image
使用了表情解析显示不出来
image
当把字体缩小成13后就能显示了
image
3.YYLabel的textVerticalAlignment属性不起作用

不支持 preferedStatusBarStyle

创建一个YYTextView() 状态栏就会变成defualt
为什么呢?

我使用的

    override func preferredStatusBarStyle() -> UIStatusBarStyle {

        return UIStatusBarStyle.LightContent

    }

来控制状态栏的。

关于TextBinding自定义

想把邮箱替换为 @联系人 这种样式的字符串,删除的时候直接删除掉该字符串,但是怎么写正则都不起作用,求教这个正则该怎么写,多谢!!!

// NSString *pattern = @"[-_a-zA-Z@.]+[ ,\n]";
NSString *pattern = @"^[@]+[ ,\n]";

YYText sizeThatFits 异常

使用原生 UITextView重写 layoutSubviews方法时调用sizeThatFits获取内容高度以适配 cell,改用了 YYText 后获取的高度始终为0

YYTextView设置的属性,在输入文字时会被清除

调试时发现:

  • (void)setMarkedText:(NSString *)markedText selectedRange:(NSRange)selectedRange {
    [self _updateIfNeeded];
    [self _endTouchTracking];
    [self _hideMenu];

    if (!NSEqualRanges(_lastTypeRange, _selectedTextRange.asRange)) {
    [self _saveToUndoStack];
    [self _resetRedoStack];
    }

    BOOL needApplyHolderAttribute = NO;
    if (_innerText.length > 0) {
    [self _updateAttributesHolder]; // 这儿,会将设置的属性重置为前面文字的属性
    } else {
    needApplyHolderAttribute = YES;
    }

这样会导致手动设置的属性被重置,不知道是不是故意这样设计的?

Missing last line sometimes with emoticon attachment.

When set label's size as textBoundingSize after YYTextLayout, it may cause missing last line when process layoutWithContainer:text:range in display task.

In my code, I've custom a YYLabel contains emoticons, it has a preferred width 232, when use YYTextLayout to calculate size, it returns line count 5 and CGSize(228, 116).

The I set the label's size as (228, 116), when it display, layoutWithContainer:text:range result line count 4.

I can fix this in my own code by keep the label width as preferred width, but it would easy trapped when someone use the textBoundingSize.

YYLabel bug

NSMutableAttributedString *text = [NSMutableAttributedString new];
UIFont *font = [UIFont boldSystemFontOfSize:16];
for (int i = 0; i < tags.count; i++) {
    NSString *tag = tags[i];
    UIColor *tagStrokeColor = UIColorHex(818e91);
    NSMutableAttributedString *tagText = [[NSMutableAttributedString alloc] initWithString:tag];
    [tagText yy_insertString:@"   " atIndex:0];
    [tagText yy_appendString:@"   "];
    tagText.yy_font = font;
    tagText.yy_color = tagStrokeColor;

    YYTextBorder *border = [YYTextBorder new];
    border.strokeWidth = 1.2f;
    border.strokeColor = tagStrokeColor;
    border.fillColor = [UIColor clearColor];
    border.cornerRadius = 100; // a huge value
    border.lineJoin = kCGLineJoinBevel;

    border.insets = UIEdgeInsetsMake(1.5, -6, 0, -6);
    [tagText yy_setTextBackgroundBorder:border range:[tagText.string rangeOfString:tag]];

    [text appendAttributedString:tagText];
}
text.yy_lineSpacing = 0;
text.yy_lineBreakMode = NSLineBreakByCharWrapping;

我的YYLabel 是写在cell上得并且自动布局强制大小的,当我的内容加起来刚好1行以内,就不会报错,而内容大于1行时,YYLabel库里面就直接crash了。

swift 中使用pod方式引用不到YYImage

具体报错如下

Undefined symbols for architecture x86_64:
  "_OBJC_CLASS_$_YYAnimatedImageView", referenced from:
      objc-class-ref in NSAttributedString+YYText.o
      objc-class-ref in YYTextView.o
  "_OBJC_CLASS_$_YYImage", referenced from:
      objc-class-ref in UIPasteboard+YYText.o
      objc-class-ref in YYTextView.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

根据内容改变容器size 单行时会跳动, 并且回车换行没有计算到高度里。

  • (void)textViewDidChange:(YYTextView *)textView {

    NSAttributedString *text = textView.attributedText;
    if ([textView.text isEqualToString:@""]) {
    text = textView.placeholderAttributedText;
    }

    CGSize size = CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX);
    YYTextLayout *layout = [YYTextLayout layoutWithContainerSize:size text:text];

    CGSize newSize = CGSizeMake(layout.textBoundingSize.width, layout.textBoundingSize.height);

    NSLog(@"layout.textBoundingSize :%@",NSStringFromCGSize(layout.textBoundingSize));
    NSLog(@"self.textView.contentSize :%@",NSStringFromCGSize(self.textView.contentSize));

    self.textView.size = newSize;
    self.textView.contentSize = newSize;

}

log:
2015-11-26 17:48:49.218 testTextView[8110:1979479] layout.textBoundingSize :{249, 23}
2015-11-26 17:48:49.218 testTextView[8110:1979479] self.textView.contentSize :{240, 50}

YYTextView 问题

YYTextContainer *newContainer = _innerContainer.mutableCopy;
这快会Crash.

Log信息:
reason: '-[YYTextContainer mutableCopyWithZone:]: unrecognized selector sent to instance 0x7ff7da64b690'

暂时改为Copy可以用.

行距问题疑问

YYText 非常棒,我已经扔掉了 TTTAttributedLabel :D
有个疑问,在文字段落时,行距有时候并没有保持一致,原因不明,见截图:
img_7582

这是一段很均匀的纯文本(无 emoji 和 Attachment,也没有任何 highlight 和 binding)
仔细看一下会发现,倒数第六行的行距和其他行不同(「。第二,科创版推出...」这一行)

具体原因不明,代码片段:

- (YYLabel *)textLabel
{
   if (!textLabel) {
       self.textLabel = [[YYLabel alloc] initWithFrame:CGRectZero];
       self.textLabel.userInteractionEnabled = YES;
       self.textLabel.font = [UIFont systemFontOfSize:kEspressoDescriptionTextFontSize];
       self.textLabel.textColor = [UIColor darkGrayColor];
       self.textLabel.lineBreakMode = NSLineBreakByCharWrapping;
       self.textLabel.textVerticalAlignment = YYTextVerticalAlignmentCenter;
       self.textLabel.numberOfLines = 0;
       self.textLabel.displaysAsynchronously = YES;
       [bubbleView addSubview:self.textLabel];
    }
    return textLabel;
}
- (YYTextLayout *)textLayoutForMessageContent:(NSString *)content font:(UIFont *)font textWidth:(CGFloat)maxWidth {
    NSMutableAttributedString *text = [[NSMutableAttributedString alloc] initWithString:content];
    text.yy_font = font;
    text.yy_color = [UIColor darkGrayColor];
    text.yy_lineSpacing = kTextLineSpacing;
    text.yy_lineBreakMode = NSLineBreakByCharWrapping;

    // 解析超链接
    [text enumerateTextParser:AKCTextMessageCheckingTypeURL];

    // 解析电话号码
    [text enumerateTextParser:AKCTextMessageCheckingTypePhoneNum];

    // 解析邮箱地址
    [text enumerateTextParser:AKCTextMessageCheckingTypeEmail];

    // 解析表情
    [text enumerateTextParser:AKCTextMessageCheckingTypeFace];

    YYTextContainer *container = [YYTextContainer new];
    container.size = CGSizeMake(maxWidth, CGFLOAT_MAX);

    YYTextLayout *layout = [YYTextLayout layoutWithContainer:container text:text];

    return layout;
}
    YYTextLayout *layout = [self textLayoutForMessageContent:msgModel.message_content font:[UIFont systemFontOfSize:16.f] textWidth:maxTextWidth];

    width = layout.textBoundingSize.width;
    height = layout.textBoundingSize.height;

    self.textLabel.frame = CGRectMake(kLeftBubbleTextLeftInset,
                                            kBubbleTextTopInset,
                                            width,
                                            height);
    self.textLabel.textLayout = layout;

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.