CCAttributedString
CCAttributedString是我整理NSMutableAttributedString中AttributedName属性封装好的一个分类,通过链式编程,可以轻松完成对富文本的编辑。不多说,看效果吧。
代码:
- (void)viewDidLoad {
[super viewDidLoad];
NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:@"通过NSRange添加效果\n给第三个123123123加特效\n给所有的123123123加特效\n拉开距离\n扁平\n脉动不回来了\n一条线两条线删除线\n空心 实心\nfl是连在一起的\n听说代写多了,眼睛会花\n凸版印刷效果\n正常状态和设置偏移量后\n让我打一套组合拳\n这句话是反的\n最后我选择滑稽"];
string.textColor([UIColor redColor]).font([UIFont systemFontOfSize:30]).range(NSMakeRange(2, 7));
string.textColor([UIColor redColor]).font([UIFont systemFontOfSize:10]).backgroundColor([UIColor darkGrayColor]).rangeIndex(2).rangeString(@[@"3",@"1"]);
string.textColor([UIColor blackColor]).font([UIFont boldSystemFontOfSize:30]).all().rangeString(@"2");
string.textSpace(10).rangeString(@"拉开距离");
string.textColor([UIColor blackColor]).font([UIFont systemFontOfSize:30]).backgroundColor([UIColor cyanColor]).rangeString(@"本质");
string.obliqueness(YES).textColor([UIColor orangeColor]).rangeString(@"脉动不回来了");
string.expansion(YES).textColor([UIColor purpleColor]).rangeString(@"扁平");
string.underline(YES).underlineColor([UIColor orangeColor]).rangeString(@"一条线");
string.underline(NSUnderlineStyleDouble).underlineColor([UIColor blueColor]).rangeString(@"两条线");
string.strikethrough(YES).strikethroughColor([UIColor redColor]).rangeString(@"删除线");
string.strokeWidth(5).strokeColor([UIColor brownColor]).font([UIFont systemFontOfSize:30]).rangeString(@"空心");
string.strokeWidth(-5).strokeColor([UIColor brownColor]).font([UIFont systemFontOfSize:30]).rangeString(@"实心");
string.ligature(YES).font([UIFont fontWithName: @"futura" size: 30]).textColor([UIColor redColor]).rangeIndex(0).rangeString(@"fl");
string.effectLetterpressStyle(YES).rangeString(@"凸版印刷效果");
string.textColor([UIColor darkGrayColor]).font([UIFont systemFontOfSize:8]).baselineOffset(10).rangeString(@"设置偏移量后");
string.textColor([UIColor grayColor]).backgroundColor([UIColor orangeColor]).textSpace(10).obliqueness(YES).expansion(YES).underline(YES).underlineColor([UIColor blueColor]).strikethrough(YES).rangeString(@"让我打一套组合拳");
string.writingDirection(@[@(NSWritingDirectionRightToLeft | NSTextWritingDirectionOverride)]).rangeString(@"这句话是反的");
NSTextAttachment *attachment = [[NSTextAttachment alloc] init];
attachment.image = [UIImage imageNamed:@"huaji"];
attachment.bounds = CGRectMake(0, -4, 20, 20);
string.attachment(attachment,string.length);
NSShadow *shadow = [[NSShadow alloc] init];
shadow.shadowColor = [UIColor darkGrayColor];
shadow.shadowOffset = CGSizeMake(2, 2);
string.shadow(shadow).rangeString(@"听说代写多了,眼睛会花");
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height*4/5)];
label.textColor = [UIColor blueColor];
label.numberOfLines = 0;
[self.view addSubview:label];
label.attributedText = string;
UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(0, self.view.frame.size.height*4/5, self.view.frame.size.width, self.view.frame.size.height/5)];
textView.delegate = self;
textView.editable = NO;
[self.view addSubview:textView];
NSMutableAttributedString *linkString = [[NSMutableAttributedString alloc] initWithString:@"textview\n这是一条链接"];
linkString.link([NSURL URLWithString:@"https://www.baidu.com"]).textColor([UIColor orangeColor]).font([UIFont systemFontOfSize:20]).underline(YES).rangeString(@"链接");
textView.attributedText = linkString;
}
效果:
熟悉Masonry的人都对链式写法司空见惯了,相比NSMutableAttributedString提供的方法,比如:
NSDictionary *attributeDict = [NSDictionary dictionaryWithObjectsAndKeys:
[UIFontsystemFontOfSize:15.0],NSFontAttributeName,
[UIColorredColor],NSForegroundColorAttributeName,
NSUnderlineStyleAttributeName,NSUnderlineStyleSingle,nil];
NSMutableAttributedString *AttributedStr = [[NSMutableAttributedStringalloc]initWithString:@"富文本" attributes:attributeDict];
使用CCAttributedString可以一行之内解决战斗,最重要的是不用每次去翻文档找那一串参数名了:
string.font([UIFont systemFontOfSize:15]).textColor([UIColor redColor]).underline(YES).rangeString(@"xxxxx");
每次添加属性的时候,都需要以range()或rangeString()结束,所有的方法说明如下:
@interface NSMutableAttributedString (CCAttributedString)
- (NSMutableAttributedString *(^)(UIColor *))textColor;//字体颜色
- (NSMutableAttributedString *(^)(UIColor *))backgroundColor;//背景颜色
- (NSMutableAttributedString *(^)(UIFont *))font;//字号
- (NSMutableAttributedString *(^)(NSUnderlineStyle))underline;//下划线
- (NSMutableAttributedString *(^)(UIColor *))underlineColor;//下划线颜色
- (NSMutableAttributedString *(^)(UIColor *))strokeColor;//描边
- (NSMutableAttributedString *(^)(CGFloat))strokeWidth;//描边宽度
- (NSMutableAttributedString *(^)(BOOL))obliqueness;//斜体
- (NSMutableAttributedString *(^)(BOOL))expansion;//扁平体
- (NSMutableAttributedString *(^)(BOOL))strikethrough;//删除线
- (NSMutableAttributedString *(^)(UIColor *))strikethroughColor;//删除线颜色
- (NSMutableAttributedString *(^)(BOOL))ligature;//连体
- (NSMutableAttributedString *(^)(NSShadow *))shadow;//字体阴影
- (NSMutableAttributedString *(^)(BOOL))effectLetterpressStyle;//凸版印刷体
- (NSMutableAttributedString *(^)(CGFloat))baselineOffset;//字体偏移
- (NSMutableAttributedString *(^)(NSURL *))link;//URL链接
- (NSMutableAttributedString *(^)(id))writingDirection;//书写方向
- (NSMutableAttributedString *(^)(CGFloat))lineSpace;//行间距
- (NSMutableAttributedString *(^)(CGFloat))textSpace;//字间距
- (NSMutableAttributedString *(^)(NSTextAttachment *,NSInteger))attachment;//插入图片
- (NSMutableAttributedString *(^)(id))rangeString;//根据一串或一组字符串添加效果
- (NSMutableAttributedString *(^)(NSRange))range;//根据range添加效果
- (NSMutableAttributedString *(^)())all;//匹配所有的rangeString,添加效果
- (NSMutableAttributedString *(^)(NSInteger))rangeIndex;//给第几个rangeString添加效果
@end
一些注意到地方有,rangeString()这个方法可以传一个或一组字符串,all()可以找到所有目标字符串,rangeIndex()可以找到第n个目标字符串,以后我还会丰富它的功能。
实现原理
链式编程
通过返回一个返回值为NSMutableAttributedString的block,可以实现这种效果
- (NSMutableAttributedString *(^)(UIColor *))textColor {
return ^ id (UIColor *color) {
self.attributedBuilder.currentTextColor = color;
return self;
};
}
我建了一个名为CCAttributedStringBuilder的类,用来保存每个方法传过来的值,并在rangeString或range调用后给NSMutableAttributedString添加属性,最后清除掉当前builder保存的属性。
@interface CCAttributedStringBuilder : NSObject
@property (nonatomic, strong) UIColor *currentTextColor;
@property (nonatomic, strong) UIColor *currentBackgroundColor;
@property (nonatomic, strong) UIFont *currentFont;
@property (nonatomic, strong) NSNumber *obliqueness;
@property (nonatomic, strong) NSNumber *Expansion;
@property (nonatomic, strong) NSNumber *textSpace;
@property (nonatomic, strong) NSNumber *underline;
@property (nonatomic, strong) UIColor *underLineColor;
@property (nonatomic, strong) UIColor *strokeColor;
@property (nonatomic, strong) NSNumber *strokeWidth;
@property (nonatomic, strong) NSNumber *strikethrough;
@property (nonatomic, strong) UIColor *strikethroughColor;
@property (nonatomic, strong) NSNumber *ligature;
@property (nonatomic, strong) NSShadow *shadow;
@property (nonatomic, strong) NSNumber *effectLetterpressStyle;
@property (nonatomic, strong) NSNumber *baselineOffset;
@property (nonatomic, strong) NSURL *link;
/**
@[@(NSWritingDirectionLeftToRight | NSTextWritingDirectionEmbedding)]
@[@(NSWritingDirectionLeftToRight | NSTextWritingDirectionOverride)]
@[@(NSWritingDirectionRightToLeft | NSTextWritingDirectionEmbedding)]
@[@(NSWritingDirectionRightToLeft | NSTextWritingDirectionOverride)]
*/
@property (nonatomic, strong) id writingDirection;
@property (nonatomic, strong) NSNumber *all;
@property (nonatomic, strong) NSNumber *rangeIndex;
@property (nonatomic, assign) BOOL isAddingInArray;
@end
- (NSMutableAttributedString *(^)(id))rangeString {
return ^ id (id rangeObj) {
void(^addBlock)(NSString *) = ^ (NSString *targetString) {
if (self.attributedBuilder.rangeIndex) {
[self addAttributesAtRangeIndexWithObj:targetString];
} else if (self.attributedBuilder.all && [self.attributedBuilder.all boolValue]) {
[self addAttributesAllWithObj:targetString];
} else {
[self addAttributesWithObj:targetString];
}
};
if ([rangeObj isKindOfClass:[NSString class]]) {
addBlock(rangeObj);
} else if ([rangeObj isKindOfClass:[NSArray class]]) {
for (id obj in rangeObj) {
if ([obj isKindOfClass:[NSString class]]) {
self.attributedBuilder.isAddingInArray = !([obj isEqual:[rangeObj lastObject]]);
addBlock(obj);
}
}
}
return self;
};
}
- (NSMutableAttributedString *(^)(NSRange))range {
return ^ id (NSRange range) {
[self addAttributesWithRange:range];
return self;
};
}
代码在Github上,拙作也望大家路过给个星星,祝大家代码越写越好。