• 单行及多行图文混排,聊天应用较常用,本文只提供算法。


    // TTSingleLineView.h
    #import <UIKit/UIKit.h>
    #import "TTLineView.h"
    
    #define kChatRoomSingleLineSendFontSize        (18.0f)
    
    @interface TTSingleLineView : TTLineView
    
    + (TTSingleLineView *)singleLineView:(NSArray *)views;
    
    @end
    
    //TTSingleLineView.m
    #import "TTSingleLineView.h"
    
    #define kChatRoomSingleLineDefaultHeight (30.0f)
    
    @implementation TTSingleLineView
    
    - (id)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
        if (self) {
            // Initialization code
    //        self.backgroundColor = [UIColor colorWithWhite:0.4f alpha:0.4f];
        }
        return self;
    }
    
    + (TTSingleLineView *)singleLineView:(NSArray *)views
    {
        TTSingleLineView *slv = [[TTSingleLineView alloc] initWithFrame:CGRectZero];
        [slv chatRoomSingleLineView:views];
        return slv;
    }
    
    - (CGFloat)chatRoomSingleLineView:(NSArray *)array
    {
        CGFloat lineWidth = 0.0f;
        for (NSDictionary *dict in array)
        {
            switch ([self contentType:dict])
            {
                case kChatRoomText:
                {
                    NSString *contentText = [self chatContentText:dict];
                    CGFloat fontSize = [self chatContentTextFont:dict];
                    CGFloat textWidth = [self getStringWidth:contentText size:fontSize];
                    ChatRoomFontColorMode colorMode = [[dict valueForKey:kChatTextColorTypeKeyName] integerValue];
                    UIColor *color = [self chatTextColor:colorMode];
                    
                    UILabel *l = [[UILabel alloc] initWithFrame:CGRectMake(lineWidth,
                                                                           0.0f,
                                                                           textWidth,
                                                                           kChatRoomSingleLineDefaultHeight)];
                    l.backgroundColor = [UIColor clearColor];
                    l.font = kFontOfSize(fontSize);
                    l.text = contentText;
                    l.textColor = color;
                    l.lineBreakMode = NSLineBreakByCharWrapping;
                    [self addSubview:l];
                    
                    lineWidth += textWidth;
                }
                    break;
                case kChatRoomRemoteDynamicImage:
                case kChatRoomRemoteStaticImage:
                {
                    NSString *imageStr = [self chatImagePath:dict];
                    CGFloat imageWidth = [self chatImageWidth:dict];
                    CGFloat imageHeight = [self chatImageHeight:dict];
                    CGFloat imagePaddingX = [self chatImagePaddingX:dict];
                    CGFloat imagePaddingY = [self chatImagePaddingY:dict];
                    
                    imageStr = [imageStr substringFromIndex:kChatCutOffContentRemoteStillImageType.length];
                    
                    UIImageView *imageView = [[UIImageView alloc] initWithFrame:
                                              CGRectMake(lineWidth + imagePaddingX,
                                                         0.0f + imagePaddingY,
                                                         imageWidth,
                                                         imageHeight)];
                    [imageView setImageWithURL:[NSURL URLWithString:imageStr] placeholderImage:nil];
                    [self addSubview:imageView];
                    
                    lineWidth += imageWidth;
                    lineWidth += imagePaddingX;
                }
                    break;
                case kChatRoomLocalDynamicImage:
                case kChatRoomLocalStaticImage:
                {
                    NSString *imageStr = [self chatImagePath:dict];
                    CGFloat imageWidth = [self chatImageWidth:dict];
                    CGFloat imageHeight = [self chatImageHeight:dict];
                    CGFloat imagePaddingX = [self chatImagePaddingX:dict];
                    CGFloat imagePaddingY = [self chatImagePaddingY:dict];
                                   
                    imageStr = [imageStr substringFromIndex:kChatCutOffContentRemoteStillImageType.length];
                    
                    UIImageView *imageView = [[UIImageView alloc] initWithFrame:
                                              CGRectMake(lineWidth + imagePaddingX,
                                                         0.0f + imagePaddingY,
                                                         imageWidth,
                                                         imageHeight)];
                    imageView.image = kImageNamed(imageStr);
                    [self addSubview:imageView];
                    
                    lineWidth += imageWidth;
                    lineWidth += imagePaddingX;
                }
                    break;
                    
                default:
                    break;
            }
        }
    
        self.frame = CGRectMake(0.0f, 0.0f, lineWidth, kChatRoomSingleLineDefaultHeight);
        
        return kChatRoomSingleLineDefaultHeight;
    }
    
    - (CGFloat)getStringWidth:(NSString *)text size:(CGFloat)fontSize
    {
        CGSize size = [text sizeWithFont:kFontOfSize(fontSize) constrainedToSize:CGSizeMake(MAXFLOAT, kChatRoomSingleLineDefaultHeight)];
        return size.width;
    }
    
    /*
    // Only override drawRect: if you perform custom drawing.
    // An empty implementation adversely affects performance during animation.
    - (void)drawRect:(CGRect)rect
    {
        // Drawing code
    }
    */
    
    @end
    
    // TTMultiLineView.h
    #import <UIKit/UIKit.h>
    #import "TTLineView.h"
    
    @interface TTMultiLineView : TTLineView
    
    @property (nonatomic, assign) CGFloat previousHeight;
    // View's total height.
    @property (nonatomic, assign) CGFloat height;
    @property (nonatomic, assign) CGFloat padding;
    
    + (TTMultiLineView *)multiLineView:(NSArray *)views;
    
    @end
    
    // TTMultiLineView.m
    #import "TTMultiLineView.h"
    
    #define kChatTextHeightDefault         (24.0f)
    #define kChatViewWidthMax              (kScreenWidth - self.padding * 2)
    #define kChatSplitSingleWordWidth      (15.0f)
    #define kChatContentPadding            (0.0f)
    
    // Parse.
    #define kChatParseTextWidthKeyName     @"chat.parse.text.width"
    #define kChatParseTextContentKeyName   @"chat.parse.text.content"
    #define kChatParseTextCutPointKeyName  @"chat.parse.text.cutpoint"
    
    @implementation TTMultiLineView
    
    - (id)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
        if (self) {
            // Initialization code
        }
        return self;
    }
    
    + (TTMultiLineView *)multiLineView:(NSArray *)views
    {
        TTMultiLineView *mlv = [[TTMultiLineView alloc] initWithFrame:CGRectZero];
        [mlv chatMultiLineView:views];
        return mlv;
    }
    
    - (CGFloat)chatMultiLineView:(NSArray *)array
    {
        CGFloat viewWidth = 0.0f;
        CGFloat viewHeightMax = 0.0f;
        
        if (self.padding == 0.0f)
        {
            self.padding = kChatContentPadding;
        }
        
        for (NSDictionary *dict in array)
        {
            switch ([self contentType:dict])
            {
                case kChatRoomText:
                {
                    NSString *contentText = [self chatContentText:dict];
                    CGFloat fontSize = [self chatContentTextFont:dict];
                    
                    if (contentText != nil && contentText.length > 0)
                    {
                        CGSize firstCharSize = [[contentText substringToIndex:1] sizeWithFont:kFontOfSize(fontSize) constrainedToSize:CGSizeMake(MAXFLOAT, kChatTextHeightDefault)];
                        
                        if (viewWidth + firstCharSize.width > kChatViewWidthMax)
                        {
                            // insert new line if last string reach end.
                            self.previousHeight += kChatTextHeightDefault;
                            viewWidth = 0.0f;
                        }
                    }
                    
                    NSArray *sectionStrs = [self splitString:contentText start:viewWidth size:fontSize];
                    
                    // Multiline.
                    NSUInteger line = 0;
                    for (NSDictionary *d in sectionStrs)
                    {
                        NSUInteger width = [[d valueForKey:kChatParseTextWidthKeyName] unsignedIntegerValue];
                        NSString *text = [d valueForKey:kChatParseTextContentKeyName];
                        
                        ChatRoomFontColorMode colorMode = [[dict valueForKey:kChatTextColorTypeKeyName] integerValue];
                        UIColor *color = [self chatTextColor:colorMode];
                        
                        if (line != 0)
                        {
                            viewWidth = 0.0f;
                            if (line == 1)
                            {
                                // First Line
                                self.previousHeight += MAX(kChatTextHeightDefault, viewHeightMax);
                                viewHeightMax = kChatTextHeightDefault;
                            }
                            else
                            {
                                // > 1 line.
                                self.previousHeight += kChatTextHeightDefault;
                            }
                        }
                        else
                        {
                            viewHeightMax = MAX(viewHeightMax, kChatTextHeightDefault);
                        }
                        
                        UILabel *l = [[UILabel alloc] initWithFrame:CGRectMake(viewWidth,
                                                                               self.previousHeight,
                                                                               width,
                                                                               kChatTextHeightDefault)];
                        l.backgroundColor = [UIColor clearColor];
                        l.font = kFontOfSize(fontSize);
                        l.text = text;
                        l.textColor = color;
                        l.lineBreakMode = NSLineBreakByCharWrapping;
    //                    l.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin;
                        [self addSubview:l];
                        
                        if (line == [sectionStrs count] - 1)
                        {
                            // Last Line, recode width.
                            viewWidth += width;
                        }
                        
                        line++;
                    }
                }
                    break;
                case kChatRoomRemoteDynamicImage:
                case kChatRoomLocalDynamicImage:
                {
                    NSString *imageStr = [self chatImagePath:dict];
                    CGFloat imageWidth = [self chatImageWidth:dict];
                    CGFloat imageHeight = [self chatImageHeight:dict];
                    CGFloat imagePaddingX = [self chatImagePaddingX:dict];
                    CGFloat imagePaddingY = [self chatImagePaddingY:dict];
                    
                    if (viewWidth + imageWidth > kChatViewWidthMax)
                    {
                        // new line
                        self.previousHeight += viewHeightMax;
                        
                        viewHeightMax = MAX(viewHeightMax, imageHeight);
                        viewWidth = 0.0f;
                    }
                    
                    imageStr = [imageStr substringFromIndex:kChatCutOffContentLocalDynamicImageType.length];
                    //                LOGINFO(@"imageStr = %@", imageStr);
                    
                    UIImageView *imageView = [[UIImageView alloc] initWithFrame:
                                              CGRectMake(viewWidth + imagePaddingX,
                                                         self.previousHeight + imagePaddingY,
                                                         imageWidth,
                                                         imageHeight)];
                    imageView.image = [UIImage sd_animatedGIFNamed:imageStr];
                    [self addSubview:imageView];
                    
                    viewWidth += imageWidth;
                    viewWidth += imagePaddingX;
                    viewHeightMax = MAX(imageHeight, viewHeightMax);
                }
                    break;
                case kChatRoomLocalStaticImage:
                case kChatRoomRemoteStaticImage:
                {
                    NSString *imageStr = [self chatImagePath:dict];
                    CGFloat imageWidth = [self chatImageWidth:dict];
                    CGFloat imageHeight = [self chatImageHeight:dict];
                    CGFloat imagePaddingX = [self chatImagePaddingX:dict];
                    CGFloat imagePaddingY = [self chatImagePaddingY:dict];
                    
                    //                LOGINFO(@"imageStr = %@", imageStr);
                    
                    if (viewWidth + imageWidth > kChatViewWidthMax)
                    {
                        // new line
                        self.previousHeight += viewHeightMax;
                        
                        viewHeightMax = MAX(viewHeightMax, imageHeight);
                        viewWidth = 0.0f;
                    }
                    
                    imageStr = [imageStr substringFromIndex:kChatCutOffContentRemoteStillImageType.length];
                    
                    UIImageView *imageView = [[UIImageView alloc] initWithFrame:
                                              CGRectMake(viewWidth + imagePaddingX,
                                                         self.previousHeight + imagePaddingY,
                                                         imageWidth,
                                                         imageHeight)];
                    [imageView setImageWithURL:[NSURL URLWithString:imageStr] placeholderImage:nil];
                    [self addSubview:imageView];
                    
                    viewWidth += imageWidth;
                    viewWidth += imagePaddingX;
                    viewHeightMax = MAX(imageHeight, viewHeightMax);
                }
                    break;
                    
                default:
                    break;
            }
        }
        
        CGFloat totalHeight = self.previousHeight + viewHeightMax;
        if (totalHeight == 0.0f)
        {
            // Text Single Line;
            totalHeight = kChatTextHeightDefault;
        }
        self.frame = CGRectMake(self.padding, 0.0f, kChatViewWidthMax, totalHeight);
        
        return totalHeight;
    }
    
    - (NSArray *)splitString:(NSString *)str start:(CGFloat)loc size:(CGFloat)fontSize
    {
        NSMutableArray *array = [NSMutableArray arrayWithCapacity:0];
        NSUInteger i = 1;
        NSUInteger location = 0;
        NSUInteger startPoint = 0;
        CGFloat startPaddingX = loc;
        
    //    LOGINFO(@"str = %@ padding = %.2f", str, x);
        
        while (i < str.length)
        {
            NSRange range = NSMakeRange(location, i - startPoint);
            
            NSString *str1 = [str substringWithRange:range];
            CGSize size = [str1 sizeWithFont:kFontOfSize(fontSize) constrainedToSize:CGSizeMake(MAXFLOAT, kChatTextHeightDefault)];
    //        LOGINFO(@"str1 = %@ size.width = %.2f", str1, size.width);
            
            if (size.width + startPaddingX + kChatSplitSingleWordWidth > kChatViewWidthMax)
            {
                startPaddingX = 0.0f;
                location += str1.length;
                startPoint = i;
                
                NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithCapacity:0];
                [dictionary setValue:@(size.width) forKey:kChatParseTextWidthKeyName];
                [dictionary setValue:str1 forKey:kChatParseTextContentKeyName];
                [dictionary setValue:@(i) forKey:kChatParseTextCutPointKeyName];
                [array addObject:dictionary];
            }
            
            i++;
        }
        
        // Last Section String.
        NSString *lastSectionStr = [str substringFromIndex:location];
        CGSize lastStrSize = [lastSectionStr sizeWithFont:kFontOfSize(fontSize) constrainedToSize:CGSizeMake(MAXFLOAT, kChatTextHeightDefault)];
        
        NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithCapacity:0];
        [dictionary setValue:@(lastStrSize.width) forKey:kChatParseTextWidthKeyName];
        [dictionary setValue:lastSectionStr forKey:kChatParseTextContentKeyName];
        [dictionary setValue:@(i) forKey:kChatParseTextCutPointKeyName];
        [array addObject:dictionary];
        
        return array;
    }
    
    /*
    // Only override drawRect: if you perform custom drawing.
    // An empty implementation adversely affects performance during animation.
    - (void)drawRect:(CGRect)rect
    {
        // Drawing code
    }
    */
    
    @end
    


  • 相关阅读:
    ExtJs自学教程(1):从一切API开始
    集成框架 javaweb开发平台ssmy_m(生成代码) java struts2 mybatis spring maven jquery
    hdu2203 KMP水的问题
    Hibernate制图(两)——许多-于─关系映射
    FPGA 异步时钟处理方
    在Magento产品页面的使用jqZoom
    struts2基本介绍
    让你提前知道软件开发(45):第一印象的代码
    struts2 模型分配问题和延迟加载问题
    性能优化(一个)Hibernate 使用缓存(一个、两、查询)提高系统性能
  • 原文地址:https://www.cnblogs.com/james1207/p/3313170.html
Copyright © 2020-2023  润新知