协议图文混排ios
2016-05-29 12:33:00 weixin_33860147 阅读数 40

使用系统自带的NSAttributedString来处理,对于一般的图文混排已经足够了,但是,有一个缺点就是NSAttributedString并不支持gif动画。实际上,使用gif动画还是挺卡的。

思路:

1.通过RegexKitLite 正则,匹配出所有需要特殊处理的字符

2.由于表情图片占用一个字符,使用直接替换范围的方式,会导致后面的表情范围不对。有两种处理方案

方案一: 

  • 使用两个数组,分别装特殊字符(文字内容,文字范围,是否为特殊字符,是否为表情)和非特殊字符,按范围排序成一个新数组
  • 循环新数组List,通过判断是否为表情和是否为特殊字符来添加appendAttributedString属性。

方案二:

通过递归的方式,每找到一个表情,先替换掉,再递归找下一个

当前,使用的是方案一,核心代码:

/**
 *  普通文字 --> 属性文字
 *
 *  @param text 普通文字
 *
 *  @return 属性文字
 */
- (NSAttributedString *)attributedTextWithText:(NSString *)text
{
    NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] init];
    
    // 表情的规则
    NSString *emotionPattern = @"\\[[0-9a-zA-Z\\u4e00-\\u9fa5]+\\]";
    // @的规则
    NSString *atPattern = @"@[0-9a-zA-Z\\u4e00-\\u9fa5-_]+";
    // #话题#的规则
    NSString *topicPattern = @"#[0-9a-zA-Z\\u4e00-\\u9fa5]+#";
    // url链接的规则
    NSString *urlPattern = @"\\b(([\\w-]+://?|www[.])[^\\s()<>]+(?:\\([\\w\\d]+\\)|([^[:punct:]\\s]|/)))";
    NSString *pattern = [NSString stringWithFormat:@"%@|%@|%@|%@", emotionPattern, atPattern, topicPattern, urlPattern];
    
    // 遍历所有的特殊字符串
    NSMutableArray *parts = [NSMutableArray array];
    [text enumerateStringsMatchedByRegex:pattern usingBlock:^(NSInteger captureCount, NSString *const __unsafe_unretained *capturedStrings, const NSRange *capturedRanges, volatile BOOL *const stop) {
        if ((*capturedRanges).length == 0) return;
        
        TextPartModel *part = [[TextPartModel alloc] init];
        part.special = YES;
        part.text = *capturedStrings;
        part.emotion = [part.text hasPrefix:@"["] && [part.text hasSuffix:@"]"];
        part.range = *capturedRanges;
        [parts addObject:part];
    }];
    
    // 遍历所有的非特殊字符
    [text enumerateStringsSeparatedByRegex:pattern usingBlock:^(NSInteger captureCount, NSString *const __unsafe_unretained *capturedStrings, const NSRange *capturedRanges, volatile BOOL *const stop) {
        if ((*capturedRanges).length == 0) return;
        
        TextPartModel *part = [[TextPartModel alloc] init];
        part.text = *capturedStrings;
        part.range = *capturedRanges;
        [parts addObject:part];
    }];
    
    // 排序
    // 系统是按照从小 -> 大的顺序排列对象
    [parts sortUsingComparator:^NSComparisonResult(TextPartModel *part1, TextPartModel *part2) {
        // NSOrderedAscending = -1L, NSOrderedSame, NSOrderedDescending
        // 返回NSOrderedSame:两个一样大
        // NSOrderedAscending(升序):part2>part1
        // NSOrderedDescending(降序):part1>part2
        if (part1.range.location > part2.range.location) {
            // part1>part2
            // part1放后面, part2放前面
            return NSOrderedDescending;
        }
        // part1<part2
        // part1放前面, part2放后面
        return NSOrderedAscending;
    }];
    
    UIFont *font = [UIFont systemFontOfSize:15];
    NSMutableArray *specials = [NSMutableArray array];
    // 按顺序拼接每一段文字
    for (TextPartModel *part in parts) {
        // 等会需要拼接的子串
        NSAttributedString *substr = nil;
        if (part.isEmotion) { // 表情
            NSTextAttachment *attch = [[NSTextAttachment alloc] init];
            NSString *name = [EmoticonTool emoticonWithChs:part.text].png;
            if (name) { // 能找到对应的图片
                attch.bounds = CGRectMake(0, -3, font.lineHeight, font.lineHeight);
                attch.image = [UIImage imageNamed:name];
                substr = [NSAttributedString attributedStringWithAttachment:attch];
            } else { // 表情图片不存在
                substr = [[NSAttributedString alloc] initWithString:part.text];
            }
        } else if (part.special) { // 非表情的特殊文字
            substr =[[NSAttributedString alloc] initWithString:part.text attributes:@{NSForegroundColorAttributeName : [UIColor redColor]
                                                                                      }];
            SpecialModel *s = [[SpecialModel alloc] init];
            s.text = part.text;
            NSUInteger loc = attributedText.length;
            NSUInteger len = part.text.length;
            s.range = NSMakeRange(loc, len);
            [specials addObject:s];
        } else { // 非特殊文字
            substr = [[NSAttributedString alloc] initWithString:part.text];
        }
        [attributedText appendAttributedString:substr];
    }
    
    // 一定要设置字体,保证计算出来的尺寸是正确的
    [attributedText addAttribute:NSFontAttributeName value:font range:NSMakeRange(0, attributedText.length)];
    [attributedText addAttribute:@"specials" value:specials range:NSMakeRange(0, 1)];
    
    return attributedText;
}
View Code

 在使用过程中,我们需要注意一点,计算文本的宽高,通过下面来计算

 [status.attributedText boundingRectWithSize:CGSizeMake(maxW, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin context:nil].size;

在计算过程中,我们并没有传字体大小,因而,我们需要给attributedText一开始设定字体大小:

// 一定要设置字体,保证计算出来的尺寸是正确的
    [attributedText addAttribute:NSFontAttributeName value:font range:NSMakeRange(0, attributedText.length)];

设置行高

    // 定义行高
    NSMutableParagraphStyle * paragraphStyle = [[NSMutableParagraphStyle alloc] init];
    [paragraphStyle setLineSpacing:5];
    [attributedText addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, attributedText.length)];

 

附源代码:http://pan.baidu.com/s/1o8Su8H0

目录说明:

HomeViewController  ---列表

StatusCell       ---列表TableCell

StatusFrame       ---列表TableCell高度。由于cell的高度是不固定的,因此我们定义StatusFrame来管理所有的控件尺寸,最后返回总高度

StatusModel      ---微博模型,图文混排处理,在这里做核心混排处理,通过添加attributedText属性处理。

  --TextPartModel  --StatusModel嵌套属性,用于记录RegexKitLite 正则匹配出的字符

  --SpecialModel   --StatusModel嵌套属性,用于特殊实符点击变色的范围比比较

  --UserModel     --StatusModel嵌套属性,用户模型

 

2015-11-12 19:18:00 weixin_34209406 阅读数 6

图文混排实现方式

  • core Text
    • ios 6.0 之前,纯C语言,不易用,不推荐使用
  • NSAttributedString
    • ios 6.0 开始,简单易用
  • TextKit
    • ios7 开始,功能强大,简单易用
  • UIWebView
    • 利用UIWebView加载HTML实现图文混排
    • 但是注意:UIWebView本身有内存问题,占用内存相比较而较大不推荐,但是使用比较灵活

1、不可变的属性文字 NSAttributedString

    NSMutableDictionary *attrs = [NSMutableDictionary dictionary];
    attrs[NSForegroundColorAttributeName] = [UIColor grayColor];
    attrs[NSUnderlineStyleAttributeName] = @1;
    attrs[NSUnderlineColorAttributeName] = [UIColor redColor];
    self.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.placeholder attributes:attrs];

2、可变的属性文字 NSMutableAttributedString

    NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:self.placeholder];
    [string addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(0, 1)];
    [string addAttribute:NSForegroundColorAttributeName value:[UIColor greenColor] range:NSMakeRange(1, 1)];
    [string addAttribute:NSFontAttributeName value:[UIFont boldSystemFontOfSize:30] range:NSMakeRange(1, 1)];
    self.attributedPlaceholder = string;

3、图文混排

  • 图解:


    831339-698b1c9530d2873c.png
    Snip20150902_94.png

    831339-6e20c1d1785aed12.png
  • 注意:


    831339-484d05a8a4302245.png
    Snip20150902_96.png
  • 实现:

  // 富文本用法3 - 图文混排
    NSMutableAttributedString *string = [[NSMutableAttributedString alloc] init];

    // 第二段:图片
    NSTextAttachment *attachment = [[NSTextAttachment alloc] init];
    attachment.image = [UIImage imageNamed:@"login_close_icon"];
    attachment.bounds = CGRectMake(0, 0, 16, 16);
    NSAttributedString *subtring2 = [NSAttributedString attributedStringWithAttachment:attachment];
    [string appendAttributedString:subtring2];

    // 第一段:placeholder
    NSAttributedString *substring1 = [[NSAttributedString alloc] initWithString:self.placeholder];
    [string appendAttributedString:substring1];

    // 第三段:哈哈
    NSAttributedString *substring3 = [[NSAttributedString alloc] initWithString:@"哈哈"];
    [string appendAttributedString:substring3];

    self.attributedPlaceholder = string;

转载于:https://www.jianshu.com/p/a8c98e684918

2017-05-03 01:50:00 weixin_33862188 阅读数 20

如图所示:这是一个字符串,在那些横线的位置我需要添加文本框来供填写。几经周折,我用了一个比较古老的方法把这个问题解决了。

贴上代码看看吧:

[objc]view plaincopy

//

//  Layout5Controller.m

//  happylearning

//

//  Created by WuShuliang on 16/3/25.

//  Copyright © 2016年 ajing. All rights reserved.

//

#import "Layout5Controller.h"

#import "ContentController.h"

#import 

#define LINE @"____________"

@interfaceLayout5Controller ()

{

NSString*_questionString;//"\n"分割后数组中的元素

NSString*questionString;//LINE分割后数组中的元素

NSMutableArray*arrayQuestion;//根据LINE把字符串分割存储在数组中

NSMutableArray*_arrayQuestionWidth;//"\n"分割后数组中的元素存进去

NSMutableArray*_arrayQuestionHeight;//"\n"分割后数组中的行数存进去

}

@end

@implementationLayout5Controller

- (void)viewDidLoad {

[superviewDidLoad];

_txtAnswer.delegate=self;

_questionString=[[NSStringalloc]init];

questionString=[[NSStringalloc]init];

arrayQuestion=[[NSMutableArrayalloc]initWithCapacity:0];

_arrayQuestionWidth=[[NSMutableArrayalloc]initWithCapacity:0];

_arrayQuestionHeight=[[NSMutableArrayalloc]initWithCapacity:0];

}

- (void)viewDidAppear:(BOOL)animated

{

//    _lblAnswer1.lineBreakMode = UILineBreakModeWordWrap;//换行模式。

[selfforCreateText];

}

//创建文本框

- (void)forCreateText

{

//1.根据“\n”把整个字符串分割存放在数组中

NSArray*arrayNo1=[_strQuestioncomponentsSeparatedByString:@"\n"];// 这里的_strQuestion就是一个字符串

NSMutableArray*arrayQuestionNo1=[NSMutableArrayarrayWithArray:arrayNo1];

//创建变量,计算整个句子的高度

CGSize detailSize = [@"the"sizeWithFont:[UIFontsystemFontOfSize:19]constrainedToSize:CGSizeMake(MAXFLOAT, MAXFLOAT)lineBreakMode:UILineBreakModeWordWrap];

//创建变量,计算“_________”的高宽度

CGSize lineSize = [LINEsizeWithFont:[UIFontsystemFontOfSize:19]constrainedToSize:CGSizeMake(MAXFLOAT, MAXFLOAT)lineBreakMode:UILineBreakModeWordWrap];

//循环取出根据“\n”分割成的数组中的数据

for(inti=0; i

_questionString=[arrayQuestionNo1objectAtIndex:i];

//判断是否含有“__________”

if([_questionStringrangeOfString:@"____________"].location!=NSNotFound) {

//2.根据“__________”把字符串分割存储在数组中

NSArray*array=[_questionStringcomponentsSeparatedByString:@"____________"];

arrayQuestion=[NSMutableArrayarrayWithArray:array];

//        NSLog(@"题目分割为:%@",arrayQuestion);

//3.判断元素个数,然后在相应位置后面追加上“__________”(便于计算创建文本框的位置)

if(arrayQuestion.count>2) {//有两个以上元素

//            NSLog(@"多根“__________”");

for(intj=0; j

if(j==0) {

//1.被“__________”分割的组成的数组的第1个元素

questionString=arrayQuestion[0];

//2.在第1个元素后边加上“__________”

arrayQuestion[0]=[NSStringstringWithFormat:@"%@%@",questionString,LINE];

//3.把元素添加到数组中,用来计算放置文本框的位置

[_arrayQuestionWidthaddObject:questionString];

[_arrayQuestionHeightaddObject:[NSStringstringWithFormat:@"%i",i]];

}

if(j==1) {

//1.被“__________”分割的组成的数组的第2个元素

questionString=[NSStringstringWithFormat:@"%@%@",arrayQuestion[0],arrayQuestion[1]];

//2.第2个元素变为前1个元素加上原本的第2个元素后边加上“__________”

arrayQuestion[1]=[NSStringstringWithFormat:@"%@%@",questionString,LINE];

//3.把元素添加到数组中,用来计算放置文本框的位置

[_arrayQuestionWidthaddObject:questionString];//

[_arrayQuestionHeightaddObject:[NSStringstringWithFormat:@"%i",i]];

}

if(j==2) {

//1.被“__________”分割的组成的数组的第3个元素

questionString=[NSStringstringWithFormat:@"%@%@",arrayQuestion[1],arrayQuestion[2]];

//2.第3个元素变为前2个元素加上原本的第3个元素后边加上“__________”

arrayQuestion[2]=[NSStringstringWithFormat:@"%@%@",questionString,LINE];

//3.把元素添加到数组中,用来计算放置文本框的位置

[_arrayQuestionWidthaddObject:questionString];

[_arrayQuestionHeightaddObject:[NSStringstringWithFormat:@"%i",i]];

}

if(j==3) {

//1.被“__________”分割的组成的数组的第4个元素

questionString=[NSStringstringWithFormat:@"%@%@",arrayQuestion[2],arrayQuestion[3]];

//2.第4个元素变为前3个元素加上原本的第4个元素后边加上“__________”

arrayQuestion[3]=[NSStringstringWithFormat:@"%@%@",questionString,LINE];

//3.把元素添加到数组中,用来计算放置文本框的位置

[_arrayQuestionWidthaddObject:questionString];

[_arrayQuestionHeightaddObject:[NSStringstringWithFormat:@"%i",i]];

}

if(j==4) {

//1.被“__________”分割的组成的数组的第5个元素

questionString=[NSStringstringWithFormat:@"%@%@",arrayQuestion[3],arrayQuestion[4]];

//2.第5个元素变为前4个元素加上原本的第5个元素后边加上“__________”

arrayQuestion[4]=[NSStringstringWithFormat:@"%@%@",questionString,LINE];

//3.把元素添加到数组中,用来计算放置文本框的位置

[_arrayQuestionWidthaddObject:questionString];

[_arrayQuestionHeightaddObject:[NSStringstringWithFormat:@"%i",i]];

}

if(j==5) {

//1.被“__________”分割的组成的数组的第6个元素

questionString=[NSStringstringWithFormat:@"%@%@",arrayQuestion[4],arrayQuestion[5]];

//2.第6个元素变为前5个元素加上原本的第6个元素后边加上“__________”

arrayQuestion[5]=[NSStringstringWithFormat:@"%@%@",questionString,LINE];

//3.把元素添加到数组中,用来计算放置文本框的位置

[_arrayQuestionWidthaddObject:questionString];

[_arrayQuestionHeightaddObject:[NSStringstringWithFormat:@"%i",i]];

}

}

}

//数组的第一个元素后边加上1根横线

else//两个和两个以下元素

{

//1.被“__________”分割的组成的数组的第一个元素

questionString=arrayQuestion[0];

//2.在第1个元素后边加上“__________”

arrayQuestion[0]=[NSStringstringWithFormat:@"%@%@",questionString,LINE];

//3.把元素添加到数组中,用来计算放置文本框的位置

[_arrayQuestionWidthaddObject:questionString];

[_arrayQuestionHeightaddObject:[NSStringstringWithFormat:@"%i",i]];

}

}

//        NSLog(@"array:%@\n%@",_arrayQuestionWidth,_arrayQuestionHeight);

}

//4.创建文本框

for(inti=0; i<_arrayQuestionWidth.count; i++) {

//计算文本框之前的长度(x坐标)

CGSize headLength=[[_arrayQuestionWidthobjectAtIndex:i]sizeWithFont:[UIFontsystemFontOfSize:19]constrainedToSize:CGSizeMake(MAXFLOAT, MAXFLOAT)lineBreakMode:UILineBreakModeWordWrap];

//第几行

NSString*strLine=[_arrayQuestionHeightobjectAtIndex:i];

intintLine=[strLineintValue];//类型转换

//在这里创建文本框

_txtAnswer=[[UITextFieldalloc]initWithFrame:CGRectMake(headLength.width, detailSize.height*intLine,lineSize.width, detailSize.height)];

_txtAnswer.font= [UIFontfontWithName:@"Arial"size:19.0f];

//         _txtAnswer.backgroundColor=[UIColor redColor];

_txtAnswer.textColor= [UIColorblackColor];

_txtAnswer.textAlignment= UITextAlignmentCenter;

//设置为YES时文本会自动缩小以适应文本窗口大小.默认是保持原来大小,而让长文本滚动

_txtAnswer.adjustsFontSizeToFitWidth=YES;

//设置自动缩小显示的最小字体大小

_txtAnswer.minimumFontSize=19;

//限制文本框输入长度(如果需要的话,就把一下方法加上)

//         [self.txtAnswer addTarget:self action:@selector(LimitTextFieldLength:) forControlEvents:UIControlEventEditingChanged];

//设置键盘的样式

_txtAnswer.keyboardType= UIKeyboardTypeDefault;

_txtAnswer.borderStyle=UITextBorderStyleNone;

//允许用户交互

self.lblAnswer1.userInteractionEnabled=true;

self.txtAnswer.userInteractionEnabled=true;

[self.lblAnswer1addSubview:_txtAnswer];

}

}

#pragma mark - 限制文字长度

-(void)LimitTextFieldLength:(id)sender{

if(_txtAnswer.text.length>25) {

_txtAnswer.text= [_txtAnswer.textsubstringToIndex:25];

}

}

// 键盘失去第一响应者

-(void)touchesBegan:(NSSet *)toucheswithEvent:(UIEvent*)event{

[self.viewendEditing:NO];

}

- (void)didReceiveMemoryWarning {

[superdidReceiveMemoryWarning];

// Dispose of any resources that can be recreated.

}

@end

2016-03-07 13:18:19 Genie12300 阅读数 384
在iOS6之前,苹果系统的图文混排技术使用coreText:如果需要使用可以使用第三方框架(纯C语言)
iOS6使用NSAttributedString、NSMutableAttributedString
iOS7 使用textKit

方法一:
NSMutableAttributedString *string = [[NSMutableAttributedStringalloc]initWithString:@"yz谁都会发生地方"];
    设置某个距离文字的颜色
    [string addAttribute:NSForegroundColorAttributeName value:[UIColor blueColor]range:NSMakeRange(0, 2)];
    [string addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:20]range:NSMakeRange(0, 2)];
设置下划线
    [string addAttribute:NSUnderlineStyleAttributeNamevalue:@(NSUnderlineStyleDouble) range:NSMakeRange(1, 3)];
添加图片
    NSTextAttachment *attach = [[NSTextAttachment alloc]init];
    attach.image = [UIImage imageNamed:@"placehold"];
可以根据字体的大小设置图片的大小,width和height为字体的size
    attach.bounds = CGRectMake(0, 0, 20, 20);
将图片转为NSAttributedString
    NSAttributedString *attachString = [NSAttributedStringattributedStringWithAttachment:attach];
将NSAttributedString拼接在string后
[注意:NSMutableAttributedString 只能拼接NSMutableAttributedString、NSAttributedString]
[string appendAttributedString:attachString];
self.textView.attributedText = string;

方法二:
使用webView和html语言以及css样式 进行图文混排  但是系统消耗较大,且webView有内存泄露
//webView图文混排
    NSString *html = @"<font color='red'></font><img src='http://'>";
UIWebView *webView = [[UIWebView alloc]initWithFrame:self.view.bounds];
[webView loadHTMLString:html baseURL:nil];
2016-08-18 22:55:14 sinat_20559947 阅读数 1271

自定义NSAttributedString分类

//  NSAttributedString+Additon.h
#import <UIKit/UIKit.h>

@interface NSAttributedString (Additon)

/// 使用图像和文本生成上下排列的属性文本
///
/// @param image      图像
/// @param imageWH    图像宽高
/// @param title      标题文字
/// @param fontSize   标题字体大小
/// @param titleColor 标题颜色
/// @param spacing    图像和标题间距
///
/// @return 属性文本
+ (instancetype)imageTextWithImage:(UIImage*)image imageWH:(CGFloat)imageWH title:(NSString*)title fontSize:(CGFloat)fontSize titleColor:(UIColor*)titleColor spacing:(CGFloat)spacing;
@end

自定义NSAttributedString分类

//
//  NSAttributedString+Additon.m

#import "NSAttributedString+Additon.h"

@implementation NSAttributedString (Additon)

+ (instancetype)imageTextWithImage:(UIImage *)image imageWH:(CGFloat)imageWH title:(NSString *)title fontSize:(CGFloat)fontSize titleColor:(UIColor *)titleColor spacing:(CGFloat)spacing {
    // 文本字典
    NSDictionary *titleDict = @{NSFontAttributeName : [UIFont systemFontOfSize:fontSize],
                                NSForegroundColorAttributeName : titleColor};
    NSDictionary *spacingDict = @{NSFontAttributeName : [UIFont systemFontOfSize:spacing]};

    // 图片文本
    NSTextAttachment *attachment = [[NSTextAttachment alloc] init];
    attachment.image = image;
    attachment.bounds = CGRectMake(0, 0, imageWH, imageWH);
    NSAttributedString *imageText = [NSAttributedString attributedStringWithAttachment:attachment];

    // 换行文本
    NSAttributedString *lineText = [[NSAttributedString alloc] initWithString:@"\n\n" attributes:spacingDict];

    // 按钮文字
    NSAttributedString *text = [[NSAttributedString alloc] initWithString:title attributes:titleDict];

    // 合并文字
    NSMutableAttributedString *attM = [[NSMutableAttributedString alloc] initWithAttributedString:imageText];
    [attM appendAttributedString:lineText];
    [attM appendAttributedString:text];

    return attM.copy;
}

@end

在按钮中使用图文混排

    UIButton *btn = [[UIButton alloc]init];

    // 创建图文混排规则(按钮-->图片&文字)
    NSAttributedString *attrStr = [NSAttributedString imageTextWithImage:[UIImage imageNamed:imageName] imageWH:40 title:title fontSize:14 titleColor:[UIColor whiteColor] spacing:8];
    // 设置图文混排
    [btn setAttributedTitle:attrStr forState:UIControlStateNormal];
    // 设置自动换行
    btn.titleLabel.numberOfLines = 0;
    // 设置文字居中
    btn.titleLabel.textAlignment = NSTextAlignmentCenter;

iOS图文混排

阅读数 428

ios图文混排

阅读数 3

iOS图文混排

阅读数 117

iOS图文混排

阅读数 6

iOS图文混排

阅读数 4

没有更多推荐了,返回首页