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

// 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


你可能感兴趣的:(算法)