2015-12-01 08:22:04 qq_31810357 阅读数 3462
  • 职场微技能 Word中的锦囊妙计

    本套Word2016视频教程由浅入深、循序渐进地介绍了Word2016软件安装、基础操作、文档基础排版、图文混排、表格编辑、长文档的编辑和排版、打印、综合案例及办公各个阶段经常遇到的各种锦囊妙计等等。

    3906 人正在学习 去看看 骆宝龙

指示根视图:(准备几张图片,把label加载在window上)

  CustomLable *label =  [[CustomLable alloc]initWithFrame:CGRectMake(0, 60, self.window.bounds.size.width, self.window.bounds.size.height)];
    label.backgroundColor = [UIColor greenColor];
    [self.window addSubview:label];

引进框架:

#import <CoreText/CoreText.h>

建一个类,继承自UILabel

返回图片的高:

// 返回图片的高
CGFloat runDelegateGetAscentCallback(void *refcon) {
    
    NSString *imageName = (__bridge NSString *)refcon;
    return [UIImage imageNamed:imageName].size.height;
    
    
}
返回图片的宽:
// 返回图片的宽
CGFloat runDelegateGetWidthCallback(void *refcon) {
//    NSString *imageName = (__bridge NSString *)refcon;
    // 让绘制图片的宽度为屏幕的宽, 使文本中只要遇到图片就换行(配合上面的换行模式)
    // 如果不想换行可以直接返回图片的宽
    
    return [UIScreen mainScreen].bounds.size.width;
    
}
CGFloat runDelegateGetDescentCallback(void *refcon){
    return 0;
}


开始绘制及相关计算:

#import "CustomLable.h"
#import <CoreText/CoreText.h>
@implementation CustomLable

- (void)drawRect:(CGRect)rect
{
    [super drawRect:rect];
    
    // 创建绘制区域
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathAddRect(path, nil, CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height));
    
    // 获取当前用于绘制画布的上下文, 用于后续将内容绘制到画布上
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    // 翻转坐标系
    // 参数1:文本宽度占Label的比例(0 ~ 1)
    // 参数2:水平方向文字逐渐往下(参数 > 0, 往上: 参数 < 0)偏移,如果是正数,逐渐向上偏移
    // 参数3:在竖直方向上,从下往上每行文字逐渐往右(参数 > 0, 往左: 参数 < 0)偏移
    // 参数4:文本首行的纵坐标占Label的比例(-1 ~ 0)
    // 参数5:文本整体往右(参数 > 0, 往左: 参数 < 0)偏移量
    // 参数6:文本整体在纵坐标方向的偏移量,参数 > label的高度, 往下偏移, 参数 < label的高度, 往上偏移
    CGContextConcatCTM(context, CGAffineTransformMake(1, 0, 0, -1, 0, self.bounds.size.height));
    
    // 准备文本
    NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc]initWithString:@"iOS程序在启动时会创建一个主线程,而在一个线程只能执行一件事情,如果在主线程执行某些耗时操作,例如加载网络图片,下载资源文件等会阻塞主线程(导致界面卡死,无法交互),所以就需要使用多线程技术来避免这类情况。iOS中有三种多线程技术 NSThread,NSOperation,GCD,这三种技术是随着IOS发展引入的,抽象层次由低到高,使用也越来越简单。"];
    
    // 改变字体大小
    [attrString addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:24] range:NSMakeRange(0, 5)];
    
    // 改变字体颜色
    [attrString addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(0, 5)];
     
     
    
    // 换行模式 (当Label的宽度不够显示内容或图片的时候就自动换行) (默认状态下如果不够显示图片, 不会自动换行, 部分图片就会看不见)
    CTParagraphStyleSetting lineBreakMode;
    CTLineBreakMode lineBreak = kCTLineBreakByCharWrapping;
    lineBreakMode.spec = kCTParagraphStyleSpecifierLineBreakMode;
    lineBreakMode.value = &lineBreak;
    lineBreakMode.valueSize = sizeof(CTLineBreakMode);
    CTParagraphStyleSetting setting[] = {lineBreakMode};
    CTParagraphStyleRef style = CTParagraphStyleCreate(setting, 1);
    NSMutableDictionary *attributes = [NSMutableDictionary dictionaryWithObject:(__bridge id)style forKey:(id)kCTParagraphStyleAttributeName];
    [attrString addAttributes:attributes range:NSMakeRange(0, attrString.length)];
    
    // 设置CTRunDelegateCallbacks 获取图片大小
    CTRunDelegateCallbacks imageCallbacks;
    imageCallbacks.version = kCTRunDelegateVersion1;
    
    // 获取图片的高 (可自由设置返回的高)
    imageCallbacks.getAscent = runDelegateGetAscentCallback;
    
    // 设置图片下一行文字距离图片的距离
    imageCallbacks.getDescent = runDelegateGetDescentCallback;
    
    // 获取图片的宽 (可自由设置返回宽度)
    imageCallbacks.getWidth = runDelegateGetWidthCallback;
    
    // 空格用于给图片留个位置
    NSMutableAttributedString *imageAttributedString = [[NSMutableAttributedString alloc]initWithString:@" "];
    
    // 根据图片占用尺寸的大小给图片留位置显示
    CTRunDelegateRef runDelegate = CTRunDelegateCreate(&imageCallbacks, (__bridge void *)(@"Untitled.png"));

    [imageAttributedString addAttribute:(NSString *)kCTRunDelegateAttributeName value:(__bridge id)runDelegate range:NSMakeRange(0, 1)];
    
    // 将图片显示在指定位置
    NSString *imageKey = @"imageName";
    [imageAttributedString addAttribute:imageKey value:@"Untitled.png" range:NSMakeRange(0, 1)];
   
    
    // 设置插入图片的位置
    [attrString insertAttributedString:imageAttributedString atIndex:38];
    
    
    //根据NSMutableAttributedString生成frame
    CTFrameRef frame = CTFramesetterCreateFrame(CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attrString), CFRangeMake(0, attrString.length), path, nil);
    
    // 开始绘制
    CTFrameDraw(frame, context);
    
    CFArrayRef lines = CTFrameGetLines(frame);
    CGPoint lineOrigins[CFArrayGetCount(lines)];
    CTFrameGetLineOrigins(frame, CFRangeMake(0, 0), lineOrigins);
    for (int i = 0; i < CFArrayGetCount(lines); i++) {
        CTLineRef line = CFArrayGetValueAtIndex(lines, i);
        CFArrayRef runs = CTLineGetGlyphRuns(line);
        for (int j = 0; j < CFArrayGetCount(runs); j++) {
            CGFloat runAscent;
            CGFloat runDescent;
            CGPoint lineOrigin = lineOrigins[i];
            CTRunRef run = CFArrayGetValueAtIndex(runs, j);
            NSDictionary *mAttrinbutes = (NSDictionary *)CTRunGetAttributes(run);
            CGRect runRect;
            runRect.size.width = CTRunGetTypographicBounds(run, CFRangeMake(0, 0), &runAscent, &runDescent, NULL);
            runRect = CGRectMake(lineOrigin.x + CTLineGetOffsetForStringIndex(line, CTRunGetStringRange(run).location, NULL), lineOrigin.y - runDescent, runRect.size.width, runAscent + runDescent);

            NSString *imageName = [mAttrinbutes objectForKey:imageKey];
            // 图片的渲染逻辑
            if (imageName) {
                UIImage *image = [UIImage imageNamed:imageName];
                CGRect imageDrawRect;
                imageDrawRect.size = image.size;
                /*
                 * 这才是放置图片的真正坐标
                 */
                // 设置图片的在X坐标的位置
                // imageDrawRect.origin.x = runRect.origin.x + lineOrigin.x;
                // 将图片放在Label的中间
                imageDrawRect.origin.x = (self.bounds.size.width - image.size.width) / 2;
                // 设置图片在y坐标的位置
                imageDrawRect.origin.y = lineOrigin.y;
                // 绘制图片
                CGContextDrawImage(context, imageDrawRect, image.CGImage);
                
                
                
            }
            
            
            
        }
        
    }
    
    
}


最终效果:


                                     

iOS开发者交流群:446310206


2016-08-01 23:49:35 hero_wqb 阅读数 3975
  • 职场微技能 Word中的锦囊妙计

    本套Word2016视频教程由浅入深、循序渐进地介绍了Word2016软件安装、基础操作、文档基础排版、图文混排、表格编辑、长文档的编辑和排版、打印、综合案例及办公各个阶段经常遇到的各种锦囊妙计等等。

    3906 人正在学习 去看看 骆宝龙

之前有写过UITableView的使用,本篇基于MVC模式实现图文混排,查看之前相关文章可以点击下面链接:

UITableView具体属性及方法可以参考文章:UITableView简介

UITableView简单使用可以参考文章:UITableView使用练习

MVC设计模式简介可以参考文章:MVC设计模式简介

基于MVC设计模式练习UITableView使用可以参考文章:基于MVC设计模式练习UITableView使用


UITableView实现图文混排,在解析数据时便计算行高保存到模型中,首先看一下效果图:


下面贴上代码:

HWTableViewController:

#import <UIKit/UIKit.h>

@interface HWTableViewController : UITableViewController

@end


#import "HWTableViewController.h"
#import "HWTableViewCell.h"
#import "HWFrameModel.h"
#import "HWModel.h"

@interface HWTableViewController ()

@property (nonatomic, strong) NSArray *HWInfoArray;

@end

@implementation HWTableViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    //隐藏系统tableViewCell分割线
    self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
    //隐藏垂直滚动条
    self.tableView.showsVerticalScrollIndicator = NO;

    //获取数据
    [self getInfo];
}

- (void)getInfo
{
    //实际开发数据是网络获取到的,这里模拟给出一个数据
    NSArray *array = @[
                       @{@"name" : @"小a", @"icon" : @"icon_h", @"text" : @"这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容", @"picture" : @"hero"},
                       @{@"name" : @"小b", @"icon" : @"icon_p", @"text" : @"这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容", @"picture" : @"hero"},
                       @{@"name" : @"小c名字很特别", @"icon" : @"icon_y", @"text" : @"这里是内容,没有配图"},
                       @{@"name" : @"小d", @"icon" : @"icon_s", @"picture" : @"hero"}];
    
    //解析数据,转模型保存
    NSMutableArray *tempArray = [NSMutableArray array];
    for (NSDictionary *dict in array) {
        HWModel *model = [HWModel modelWithDict:dict];
        HWFrameModel *frameModel = [[HWFrameModel alloc] init];
        frameModel.model = model;
        [tempArray addObject:frameModel];
    }
    self.HWInfoArray = [tempArray copy];
}

#pragma mark - Table view data source
//组数
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

//组中行数
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.HWInfoArray.count;
}

//cell内容
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    HWTableViewCell *cell = [HWTableViewCell cellWIthTableView:tableView];
    
    cell.frameModel = self.HWInfoArray[indexPath.row];
    
    return cell;
}

//设置行高
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    HWFrameModel *frameModel = self.HWInfoArray[indexPath.row];
    
    return frameModel.cellHeight;
}

@end

HWModel:

#import <Foundation/Foundation.h>

@interface HWModel : NSObject

@property (nonatomic, copy) NSString *icon;
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *text;
@property (nonatomic, copy) NSString *picture;

- (id)initWithDict:(NSDictionary *)dict;
+ (id)modelWithDict:(NSDictionary *)dict;

@end


#import "HWModel.h"

@implementation HWModel

- (id)initWithDict:(NSDictionary *)dict
{
    self = [super init];
    if (self) {
        [self setValuesForKeysWithDictionary:dict];
    }
    return self;
}

+ (id)modelWithDict:(NSDictionary *)dict
{
    return [[self alloc] initWithDict:dict];
}

@end

HWFrameModel:

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@class HWModel;

@interface HWFrameModel : NSObject

@property (nonatomic, assign) CGRect iconFrame;
@property (nonatomic, assign) CGRect nameFrame;
@property (nonatomic, assign) CGRect textFrame;
@property (nonatomic, assign) CGRect pictureFrame;
@property (nonatomic, assign) CGFloat cellHeight;
@property (nonatomic, strong) HWModel *model;

@end


#import "HWFrameModel.h"
#import "HWModel.h"

#define mainW [UIScreen mainScreen].bounds.size.width
#define HWTextFont [UIFont systemFontOfSize:15]

@implementation HWFrameModel

- (void)setModel:(HWModel *)model
{
    _model = model;
    
    //头像
    CGFloat padding = 10;
    CGFloat iconWH = 30;
    self.iconFrame = CGRectMake(padding, padding, iconWH, iconWH);
    
    //名字
    CGSize nameSize = [self sizeWithText:model.name font:HWTextFont maxSize:CGSizeMake(MAXFLOAT, MAXFLOAT)];
    CGFloat nameW = nameSize.width;
    CGFloat nameH = nameSize.height;
    CGFloat nameX = CGRectGetMaxX(self.iconFrame) + padding;
    CGFloat nameY = CGRectGetMinY(self.iconFrame);
    self.nameFrame = CGRectMake(nameX, nameY, nameW, nameH);
    
    //文字内容
    CGSize textSize = [self sizeWithText:model.text font:HWTextFont maxSize:CGSizeMake(mainW - padding * 2, MAXFLOAT)];
    self.textFrame = CGRectMake(padding, iconWH + padding * 2, textSize.width, textSize.height);
    
    //配图
    if (model.picture) {
        self.pictureFrame = CGRectMake(padding, CGRectGetMaxY(self.textFrame) + padding, 120, 120);
        _cellHeight = CGRectGetMaxY(self.pictureFrame) + padding;
    }
    else {
        _cellHeight = CGRectGetMaxY(self.textFrame) + padding;
    }
}

//根据字体大小、限定长度动态获取文字宽高尺寸
- (CGSize)sizeWithText:(NSString *)text font:(UIFont *)font maxSize:(CGSize)maxSize
{
    NSDictionary *dict = @{NSFontAttributeName : font};
    return [text boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:dict context:nil].size;
}

@end

HWTableViewCell:

#import <UIKit/UIKit.h>

@class HWFrameModel;

@interface HWTableViewCell : UITableViewCell

@property (nonatomic, strong) HWFrameModel *frameModel;

+ (instancetype)cellWIthTableView:(UITableView *)tableView;

@end


#import "HWTableViewCell.h"
#import "HWFrameModel.h"
#import "HWModel.h"

#define HWTextFont [UIFont systemFontOfSize:15]

@interface HWTableViewCell ()

@property (nonatomic, weak) UIImageView *icon;
@property (nonatomic, weak) UILabel *name;
@property (nonatomic, weak) UILabel *text;
@property (nonatomic, assign) UIImageView *picture;

@end

@implementation HWTableViewCell

+ (instancetype)cellWIthTableView:(UITableView *)tableView
{
    //cell复用,唯一标识
    static NSString *identifier = @"HWCell";
    //先在缓存池中取
    HWTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
    //缓存池中没有再创建,并添加标识,cell移出屏幕时放入缓存池以复用
    if (cell == nil) {
        cell = [[HWTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
    }
    
    return cell;
}

//重写init方法构建cell内容
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
        //取消点击高亮状态
        self.selectionStyle = UITableViewCellSelectionStyleNone;
        
        //头像
        UIImageView *icon = [[UIImageView alloc] init];
        [self.contentView addSubview:icon];
        self.icon = icon;
        
        //名字
        UILabel *name = [[UILabel alloc] init];
        name.font = HWTextFont;
        [self.contentView addSubview:name];
        self.name = name;
        
        //内容
        UILabel *text = [[UILabel alloc] init];
        text.numberOfLines = 0;
        text.font = HWTextFont;
        [self.contentView addSubview:text];
        self.text = text;
        
        //配图
        UIImageView *picture = [[UIImageView alloc] init];
        [self.contentView addSubview:picture];
        self.picture = picture;
    }
    
    return self;
}

//重写set方法,模型传递
- (void)setFrameModel:(HWFrameModel *)frameModel
{
    _frameModel = frameModel;
    
    HWModel *model = frameModel.model;
    
    self.icon.image = [UIImage imageNamed:model.icon];
    self.icon.frame = frameModel.iconFrame;
    
    self.name.text = model.name;
    self.name.frame = frameModel.nameFrame;
    
    self.text.text = model.text;
    self.text.frame = frameModel.textFrame;
    
    self.picture.image = [UIImage imageNamed:model.picture];
    self.picture.frame = frameModel.pictureFrame;
}

@end




2015-08-23 17:29:27 joonchen111 阅读数 1410
  • 职场微技能 Word中的锦囊妙计

    本套Word2016视频教程由浅入深、循序渐进地介绍了Word2016软件安装、基础操作、文档基础排版、图文混排、表格编辑、长文档的编辑和排版、打印、综合案例及办公各个阶段经常遇到的各种锦囊妙计等等。

    3906 人正在学习 去看看 骆宝龙

     本人做ios开发有一定的时间了,由于工作忙和自己懒得写,所以一直没有写过技术博客,今日突发奇想,还是写点东西吧,分享给大家。好今天我简单介绍下ios开发中图文混排的一些内容.

    图文混排呢说直白点就是图片和文字排在一起,ios中常用的一些控件都可以进行图文混排,比如UIButton、UIlabel、UITextView等等很多,我们只需要设置它们的

attributedText就可以了,比如我们在UILabel中 显示文字和图片:

//1.创建一个可变属性字符串
    NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:@"人算不如天算,中国央行的决策者估计会没有预料到,8月11日突然对人民币主动贬值会对国内外市场产生如此巨大的影响与冲击。人民币贬值后,不仅严重地冲击全球资本市场,也完全改变了国内金融市场形势。"];
    //2.创建图片附件
    NSTextAttachment *attach=[[NSTextAttachment alloc]init];
    attach.image=[UIImage imageNamed:@"dog"];
    attach.bounds=CGRectMake(40, 10, 80, 50);
    //3.创建属性字符串 通过图片附件
    NSAttributedString *attrStr=[NSAttributedString attributedStringWithAttachment:attach];
    //4.把NSAttributedString添加到NSMutableAttributedString里面
    [string appendAttributedString:attrStr];
    //5.赋值给UIlabel
    self.label.attributedText=string;
效果图如下

2013-11-05 14:18:52 javayujiafeng 阅读数 15684
  • 职场微技能 Word中的锦囊妙计

    本套Word2016视频教程由浅入深、循序渐进地介绍了Word2016软件安装、基础操作、文档基础排版、图文混排、表格编辑、长文档的编辑和排版、打印、综合案例及办公各个阶段经常遇到的各种锦囊妙计等等。

    3906 人正在学习 去看看 骆宝龙

在iOS开发中经常会遇到一些图文混排的情况,特别是在微博类应用的开发过程中经常会遇到各种表情,各种链接的解析。笔者在实践开发中经历了几次这种类型的开发,由最开始的利用WebView进行布局到最后利用富文本进行布局,对该部分的开发积累了一定的经验,现对富文本与正则表达式混用实现图文混排进行总结:

一.富文本

     WebView虽然也可以实现图文混排的效果,但是在使用的时候比较复杂,而且WebVIew的内存泄漏相当明显,使用不好反而得补偿失。现在很多的新闻类App都采用自己写的富文本进行图文混排。在很多情况下,富文本表现予外的是一个Label,将要显示的内容通过正则等封装成HTML字符串,然后显示在界面上,

下面就是按照步骤实现这一功能:

(1)先下载已经封装好的富文本标签类RCLabel(http://www.okbase.net/file/item/20694)

    该类是由一牛人封装好的用于实现图文混排的富文本类,在下载下来的源代码中可以看到其用法,但是这里有一个较为复杂的问题是你每次都需要手动将你要显示的内容封装成HTML格式的文本,这个过程相当繁琐而且容易出错,所以我在这个基础上进行了改进,将封装HTML的方法通过正则表达式独立开来,这样就实现了RCLabel与正则实现图文混排,以下是代码:

     将字符串转化成HTML的正则如下:

   .h文件

      

#import <Foundation/Foundation.h>


@interface HtmlString : NSString


+ (NSString *)transformString:(NSString *)originalStr;


@end


.m 文件如下:

#import "HtmlString.h"

#import <Foundation/NSObjCRuntime.h>

#import "RegexKitLite.h"


@implementation HtmlString


+ (NSString *)transformString:(NSString *)originalStr

{

    NSString *text = originalStr;

    

    //解析http://短链接

    NSString *regex_http =@"http(s)?://([a-zA-Z|\\d]+\\.)+[a-zA-Z|\\d]+(/[a-zA-Z|\\d|\\-|\\+|_./?%&=]*)?";//http://短链接正则表达式

    NSArray *array_http = [text componentsMatchedByRegex:regex_http];

    

    if ([array_http count]) {

        for (NSString *strin array_http) {

            NSRange range = [text rangeOfString:str];

            NSString *funUrlStr = [NSStringstringWithFormat:@"<a href=%@>%@</a>",str, str];

            text = [text stringByReplacingCharactersInRange:NSMakeRange(range.location, str.length)withString:funUrlStr];

        }

    }


    //解析@

    NSString *regex_at =@"@[\\u4e00-\\u9fa5\\w\\-]+";//@的正则表达式

    NSArray *array_at = [text componentsMatchedByRegex:regex_at];

    if ([array_at count]) {

        NSMutableArray *test_arr = [[NSMutableArrayalloc]init];

        for (NSString *strin array_at) {

            NSRange range = [text rangeOfString:str];

            if (![test_arr containsObject:str]) {

                [test_arr addObject:str];

                NSString *funUrlStr = [NSStringstringWithFormat:@"<a href=%@>%@</a>",str, str];

                text = [text stringByReplacingCharactersInRange:NSMakeRange(range.location, [str length]) withString:funUrlStr];

            }

        }

        [test_arr release];

    }

    

    

    //解析&

    NSString *regex_dot =@"\\$\\*?[\u4e00-\u9fa5|a-zA-Z|\\d]{2,8}(\\((SH|SZ)?\\d+\\))?";//&的正则表达式

    NSArray *array_dot = [text componentsMatchedByRegex:regex_dot];

    if ([array_dot count]) {

        NSMutableArray *test_arr = [[NSMutableArrayalloc]init];

        for (NSString *strin array_dot) {

            NSRange range = [text rangeOfString:str];

            if (![test_arr containsObject:str]) {

                [test_arr addObject:str];

                NSString *funUrlStr = [NSStringstringWithFormat:@"<a href=%@>%@</a>",str, str];

                text = [text stringByReplacingCharactersInRange:NSMakeRange(range.location, [str length]) withString:funUrlStr];

            }

        }

        [test_arr release];

    }


    //解析话题

    NSString *regex_pound = @"#([^\\#|.]+)#";//话题的正则表达式

    NSArray *array_pound = [text componentsMatchedByRegex:regex_pound];

    

    if ([array_pound count]) {

        for (NSString *strin array_pound) {

            NSRange range = [text rangeOfString:str];

            NSString *funUrlStr = [NSStringstringWithFormat:@"<a href=%@>%@</a>",str, str];

            text = [text stringByReplacingCharactersInRange:NSMakeRange(range.location, [strlength])withString:funUrlStr];

        }

    }


    //解析表情

    NSString *regex_emoji =@"\\[[a-zA-Z0-9\\u4e00-\\u9fa5]+\]";//表情的正则表达式

    NSArray *array_emoji = [text componentsMatchedByRegex:regex_emoji];

    NSString *filePath = [[[NSBundlemainBundle]resourcePath]stringByAppendingPathComponent:@"emotionImage.plist"];

    NSDictionary *m_EmojiDic = [[NSDictionaryalloc]initWithContentsOfFile:filePath];

   // NSString *path = [NSString stringWithFormat:@"%@", [[NSBundle mainBundle] bundlePath]];

    

    if ([array_emoji count]) {

        for (NSString *strin array_emoji) {

            NSRange range = [text rangeOfString:str];

            NSString *i_transCharacter = [m_EmojiDicobjectForKey:str];

            if (i_transCharacter) {

                //NSString *imageHtml = [NSString stringWithFormat:@"<img src = 'file://%@/%@' width='12' height='12'>", path, i_transCharacter];

                NSString *imageHtml = [NSStringstringWithFormat:@"<img src =%@>",  i_transCharacter];

                text = [text stringByReplacingCharactersInRange:NSMakeRange(range.location, [str length]) withString:[imageHtmlstringByAppendingString:@" "]];

            }

        }

    }

    [m_EmojiDic release];

    //返回转义后的字符串

    return text;

}


@end



那么在使用的时候如下:

    // contentStr为你要显示的图文字符串

   NSString *str = [HtmlStringtransformString:contentStr];

    textLabel = [[RCLabelalloc]initWithFrame:CGRectMake(10,160,300,84)];

    textLabel.delegate =self;

    textLabel.sizeDelegate =self;

    [textLabelsetFont:[UIFontfontWithName:TextNamesize:15]];

    RCLabelComponentsStructure *componentsDS = [RCLabelextractTextStyle:textString];

    textLabel.componentsAndPlainText = componentsDS;

    CGSize optimalSize = [textLabeloptimumSize:YES];   //计算图文混排后的高度

    textLabel.frame=CGRectMake(10,180,300, optimalSize.height+5);

    textLabel.lineBreakMode =NSLineBreakByCharWrapping;

    textLabel.backgroundColor = [UIColorclearColor];

    textLabel.textColor = [UIColorcolorWithRed:33.0/255green:33.0/255blue:33.0/255alpha:1];

    [self.viewaddSubview:textLabel];


   如果你在实现图文混排时还有超链接、@、$等,在最后实现该类的代理方法

-(void)RCLabel:(id)RCLabel didSelectLinkWithURL:(NSString *)url

{   // url为超链接的文字内容



效果图如下:

 


下面提供一个详细的图文混排的DEMO,该DEMO包含了AFJSONRequest的用法,异步加在图片的用法,以及RCLabel与正则表达的用法

请点击下载


效果图




2015-11-16 20:52:56 feiyuyuan_9257 阅读数 432
  • 职场微技能 Word中的锦囊妙计

    本套Word2016视频教程由浅入深、循序渐进地介绍了Word2016软件安装、基础操作、文档基础排版、图文混排、表格编辑、长文档的编辑和排版、打印、综合案例及办公各个阶段经常遇到的各种锦囊妙计等等。

    3906 人正在学习 去看看 骆宝龙

在很多新闻类或有文字展示的应用中现在都会出现图文混排的界面例如网易新闻等,乍一看去相似一个网页,其实这样效果并非由UIWebView 加载网页实现。现在分享一种比较简单的实现方式



iOS sdk中为我们提供了一套完善的文字排版开发组件:CoreText。CoreText库中提供了很多的工具来对文本进行操作,例如CTFont、CTLine、CTFrame等。利用这些工具可以对文字字体每一行每一段落进行操作。

此例中默认图片都在右上方,且为了美观和开发简便设定所占宽度都相同。

 

1.         首先,需要引入CoreText库

 

在需要使用的类文件中添加#import <CoreText/CoreText.h>头文件。

2.         设置文本的参数

创建一个NSMutableAttributedString对象,包含所需展示的文本字符串。这样就可以对其进行设置了。通过CTFontCreateWithName函数创建一个CTFont对象,利用NSMutableAttributedString对象的addAttribute方法进行设置。类似的方法可以设置字间距。

对其方式与行间距的设置方式:

  1. // 文本对齐方式   
  2.     CTTextAlignment alignment = kCTLeftTextAlignment;   
  3.     CTParagraphStyleSetting alignmentStyle;   
  4.     alignmentStyle.spec = kCTParagraphStyleSpecifierAlignment;   
  5.     alignmentStyle.valueSize = sizeof(alignment);   
  6.     alignmentStyle.value = &alignment;   
  7.  // 创建设置数组   
  8.             CTParagraphStyleSetting settings[] ={alignmentStyle};   
  9. CTParagraphStyleRef style = CTParagraphStyleCreate(settings, 1);   

同样使用addAttribute设置字符串对象。这样的方法还可以设置行间距,段间距等参数。

3.         计算图片所占高度。图片可以使用UIImageView 来进行显示。很容易便可获取每张图片所占总高度。

4.         由于图片宽度是固定的这样就可以计算每行文字缩短的字数。只要文本的总体高度低于图像总高度则文字长度都是缩短的。用CTTypesetterSuggestLineBreak函数动态的计算每一行里的字数,因为每一行里面的中文字、标点符号、数字、字母都不一样所以可以显示的字数肯定也是不同的,所以需要作这样的计算。这样循环直至文本结束,就可以知道有多少行字了。再根据字体高度和行间距得出总的文本高度,如果文本高度大于图片总高度那么显示区域的Frame高度就是文本的高度,反之亦然。

5.         绘制文本:

设置每一行绘制文本的区间:

  1. CFRange lineRange = CFRangeMake(currentIndex, lineLength);   
  2. 建立文本行对象   
  3. CTLineRef line = CTTypesetterCreateLine(typeSetter, lineRange);   
  4. CGFloat x = [self textOffsetForLine:line inRect:self.bounds];   
  5. // 设置一行的位置   
  6. CGContextSetTextPosition(context, x, y);   
  7. // 绘制一行文字   
  8.     CTLineDraw(line, context);   

6.         其他功能:

在完成文本绘制功能后可以加入调整文字大小的功能,和图片的放大的功能。

文字大小可以通过直接设置字体大小后重新绘制文本来实现。

图片放大可以在视图上添加一个新的UIImageView 来展示放大后的图片,并且加入动画效



实现代码:

  1. void RunDelegateDeallocCallback( void* refCon ){  
  2.       
  3. }  
  4.   
  5. CGFloat RunDelegateGetAscentCallback( void *refCon ){  
  6.     NSString *imageName = (NSString *)refCon;  
  7.     return 80;//[UIImage imageNamed:imageName].size.height;  
  8. }  
  9.   
  10. CGFloat RunDelegateGetDescentCallback(void *refCon){  
  11.     return 0;  
  12. }  
  13.   
  14. CGFloat RunDelegateGetWidthCallback(void *refCon){  
  15.     NSString *imageName = (NSString *)refCon;  
  16.     return 100;//[UIImage imageNamed:imageName].size.width;  
  17. }  

先设置一个CTRun的委托,主要是用于指定对象的上行高,宽,或上下文释放时使用。

  1. -(void)drawCharAndPicture  
  2. {  
  3.     CGContextRef context = UIGraphicsGetCurrentContext();  
  4.       
  5.     CGContextSetTextMatrix(context, CGAffineTransformIdentity);//设置字形变换矩阵为CGAffineTransformIdentity,也就是说每一个字形都不做图形变换  
  6.       
  7.     CGAffineTransform flipVertical = CGAffineTransformMake(1,0,0,-1,0,self.bounds.size.height);  
  8.     CGContextConcatCTM(context, flipVertical);//将当前context的坐标系进行flip  
  9.     NSLog(@"bh=%f",self.bounds.size.height);  
  10.       
  11.     NSMutableAttributedString *attributedString = [[[NSMutableAttributedString alloc] initWithString:@"请在这里插入一张图片位置"] autorelease];  
  12.       
  13.       
  14.     //为图片设置CTRunDelegate,delegate决定留给图片的空间大小  
  15.     NSString *imgName = @"img.png";  
  16.     CTRunDelegateCallbacks imageCallbacks;  
  17.     imageCallbacks.version = kCTRunDelegateVersion1;  
  18.     imageCallbacks.dealloc = RunDelegateDeallocCallback;  
  19.     imageCallbacks.getAscent = RunDelegateGetAscentCallback;  
  20.     imageCallbacks.getDescent = RunDelegateGetDescentCallback;  
  21.     imageCallbacks.getWidth = RunDelegateGetWidthCallback;  
  22.     CTRunDelegateRef runDelegate = CTRunDelegateCreate(&imageCallbacks, imgName);  
  23.     NSMutableAttributedString *imageAttributedString = [[NSMutableAttributedString alloc] initWithString:@" "];//空格用于给图片留位置  
  24.     [imageAttributedString addAttribute:(NSString *)kCTRunDelegateAttributeName value:(id)runDelegate range:NSMakeRange(0, 1)];  
  25.     CFRelease(runDelegate);  
  26.       
  27.     [imageAttributedString addAttribute:@"imageName" value:imgName range:NSMakeRange(0, 1)];  
  28.       
  29.     [attributedString insertAttributedString:imageAttributedString atIndex:4];  
  30.       
  1.     //换行模式  
  2.     CTParagraphStyleSetting lineBreakMode;  
  3.     CTLineBreakMode lineBreak = kCTLineBreakByCharWrapping;  
  4.     lineBreakMode.spec = kCTParagraphStyleSpecifierLineBreakMode;  
  5.     lineBreakMode.value = &lineBreak;  
  6.     lineBreakMode.valueSize = sizeof(CTLineBreakMode);  
  7.       
  8.     CTParagraphStyleSetting settings[] = {  
  9.         lineBreakMode  
  10.     };  
  11.       
  12.     CTParagraphStyleRef style = CTParagraphStyleCreate(settings, 1);  
  13.       
  14.           
  15.     // build attributes  
  16.     NSMutableDictionary *attributes = [NSMutableDictionary dictionaryWithObject:(id)style forKey:(id)kCTParagraphStyleAttributeName ];  
  17.       
  18.     // set attributes to attributed string  
  19.     [attributedString addAttributes:attributes range:NSMakeRange(0, [attributedString length])];  
  20.       
  21.   
  22.       
  23.     CTFramesetterRef ctFramesetter = CTFramesetterCreateWithAttributedString((CFMutableAttributedStringRef)attributedString);  
  24.       
  25.     CGMutablePathRef path = CGPathCreateMutable();  
  26.     CGRect bounds = CGRectMake(0.0, 0.0, self.bounds.size.width, self.bounds.size.height);  
  27.     CGPathAddRect(path, NULL, bounds);  
  28.       
  29.     CTFrameRef ctFrame = CTFramesetterCreateFrame(ctFramesetter,CFRangeMake(0, 0), path, NULL);  
  30.     CTFrameDraw(ctFrame, context);  
  31.       
  32.     CFArrayRef lines = CTFrameGetLines(ctFrame);  
  33.     CGPoint lineOrigins[CFArrayGetCount(lines)];  
  34.     CTFrameGetLineOrigins(ctFrame, CFRangeMake(0, 0), lineOrigins);  
  35.     NSLog(@"line count = %ld",CFArrayGetCount(lines));  
  36.     for (int i = 0; i < CFArrayGetCount(lines); i++) {  
  37.         CTLineRef line = CFArrayGetValueAtIndex(lines, i);  
  38.         CGFloat lineAscent;  
  39.         CGFloat lineDescent;  
  40.         CGFloat lineLeading;  
  41.         CTLineGetTypographicBounds(line, &lineAscent, &lineDescent, &lineLeading);  
  42.         NSLog(@"ascent = %f,descent = %f,leading = %f",lineAscent,lineDescent,lineLeading);  
  43.           
  44.         CFArrayRef runs = CTLineGetGlyphRuns(line);  
  45.         NSLog(@"run count = %ld",CFArrayGetCount(runs));  
  46.         for (int j = 0; j < CFArrayGetCount(runs); j++) {  
  47.             CGFloat runAscent;  
  48.             CGFloat runDescent;  
  49.             CGPoint lineOrigin = lineOrigins[i];  
  50.             CTRunRef run = CFArrayGetValueAtIndex(runs, j);  
  51.             NSDictionary* attributes = (NSDictionary*)CTRunGetAttributes(run);  
  52.             CGRect runRect;  
  53.             runRect.size.width = CTRunGetTypographicBounds(run, CFRangeMake(0,0), &runAscent, &runDescent, NULL);  
  54.             NSLog(@"width = %f",runRect.size.width);  
  55.               
  56.             runRect=CGRectMake(lineOrigin.x + CTLineGetOffsetForStringIndex(line, CTRunGetStringRange(run).location, NULL), lineOrigin.y - runDescent, runRect.size.width, runAscent + runDescent);  
  57.               
  58.             NSString *imageName = [attributes objectForKey:@"imageName"];  
  59.             //图片渲染逻辑  
  60.             if (imageName) {  
  61.                 UIImage *image = [UIImage imageNamed:imageName];  
  62.                 if (image) {  
  63.                     CGRect imageDrawRect;  
  64.                     imageDrawRect.size = image.size;  
  65.                     imageDrawRect.origin.x = runRect.origin.x + lineOrigin.x;  
  66.                     imageDrawRect.origin.y = lineOrigin.y;  
  67.                     CGContextDrawImage(context, imageDrawRect, image.CGImage);  
  68.                 }  
  69.             }  
  70.         }  
  71.     }  
  72.       
  73.     CFRelease(ctFrame);  
  74.     CFRelease(path);  
  75.     CFRelease(ctFramesetter);  
  76. }  

效果:



从上面看大家可能没有发现什么问题,当把图片放在字的最左边会是什么样子的?


因此为了避免这种情况发生,我在代码中添加了换行模式。添加换行后的效果:



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