首页 > 代码库 > UI基础之UITableView案例QQ聊天界面
UI基础之UITableView案例QQ聊天界面
数据模型:
#import <Foundation/Foundation.h>typedef enum{ LLMessageTypeMe, LLMessageTypeOther}LLMessageType;@interface LLMessage : NSObject/** * time */@property (nonatomic, copy) NSString *time;/** * text */@property (nonatomic, copy) NSString *text;/** * type 定义为枚举类型的好处 */@property (nonatomic, assign) LLMessageType type;/** * hiddenTime 时间是否隐藏 */@property (nonatomic, assign, getter=isHiddenTime) BOOL hiddenTime;- (instancetype)initWithDic:(NSDictionary *)dic;+ (instancetype)messageWithDic:(NSDictionary *)dic;+ (NSMutableArray *)messageList;@end
#import "LLMessage.h"@implementation LLMessage- (instancetype)initWithDic:(NSDictionary *)dic{ if (self = [super init]) { [self setValuesForKeysWithDictionary:dic]; } return self;}+ (instancetype)messageWithDic:(NSDictionary *)dic{ return [[self alloc] initWithDic:dic];}+ (NSMutableArray *)messageList{ NSString *path = [[NSBundle mainBundle] pathForResource:@"messages" ofType:@"plist"]; NSArray *dicArr = [NSArray arrayWithContentsOfFile:path]; NSMutableArray *tmpArr = [[NSMutableArray alloc] initWithCapacity:dicArr.count]; for (NSDictionary *dic in dicArr) { LLMessage *endMessage = [tmpArr lastObject]; LLMessage *message = [LLMessage messageWithDic:dic]; if ([message.time isEqualToString:endMessage.time]) { message.hiddenTime = YES; } [tmpArr addObject:message]; } return tmpArr;}@end
frame模型
#import <Foundation/Foundation.h>#import <UIKit/UIKit.h>#define LLTIMEFONT [UIFont systemFontOfSize:12]#define LLTEXTFONT [UIFont systemFontOfSize:13]#define LLPADDING 20@class LLMessage;@interface LLMessageFrame : NSObject@property (nonatomic, strong) LLMessage *message;@property (nonatomic, assign,readonly) CGRect timeF;@property (nonatomic, assign, readonly) CGRect textF;@property (nonatomic, assign, readonly) CGRect iconF;@property (nonatomic, assign, readonly) CGFloat cellHeight;+ (NSMutableArray *)messageFrameList;@end
#import "LLMessageFrame.h"#import "LLMessage.h"#import "NSString+LLNSStringExtension.h"@implementation LLMessageFrame+ (NSMutableArray *)messageFrameList{ NSMutableArray *messageArr = [LLMessage messageList]; NSMutableArray *tmpArray = [[NSMutableArray alloc] initWithCapacity:messageArr.count]; for (LLMessage *message in messageArr) { LLMessageFrame *frame = [[LLMessageFrame alloc] init]; frame.message = message; [tmpArray addObject:frame]; } return tmpArray;}- (void)setMessage:(LLMessage *)message{ _message = message; CGFloat margin = 10; // 时间 CGFloat timeX = 0; CGFloat timeY = 0; CGFloat timeW = 320; CGFloat timeH = 40; if (!message.isHiddenTime){ _timeF = CGRectMake(timeX, timeY, timeW, timeH); } // icon CGFloat iconY = CGRectGetMaxY(_timeF); CGFloat iconWH = 30; CGFloat iconX; if (message.type == LLMessageTypeMe) { // Me iconX = timeW - iconWH - margin; } else { // Other iconX = margin; } _iconF = CGRectMake(iconX, iconY, iconWH, iconWH); // text CGFloat textY = iconY; CGSize textSize = [message.text textOfSize:CGSizeMake(200, MAXFLOAT) font:LLTEXTFONT]; CGSize buttonSize = CGSizeMake(textSize.width + LLPADDING * 2, textSize.height + LLPADDING * 2); CGFloat textX; if (message.type == LLMessageTypeMe) { // Me textX = iconX - margin - buttonSize.width; } else { textX = CGRectGetMaxX(_iconF) + margin; } _textF = (CGRect){{textX, textY} , buttonSize}; CGFloat textMaxY = CGRectGetMaxY(_textF); CGFloat iconMaxY = CGRectGetMaxY(_iconF); _cellHeight = MAX(textMaxY, iconMaxY); }@end
代码自定义cell
#import <UIKit/UIKit.h>@class LLMessageFrame;@interface LLMessageCell : UITableViewCell@property (nonatomic, strong) LLMessageFrame *messageFrame;+ (instancetype)messageCellWith:(UITableView *)tableView;@end
#import "LLMessageCell.h"#import "LLMessageFrame.h"#import "LLMessage.h"#import <UIKit/UIKit.h>#import "UIImage+LLUIImageExtension.h"@interface LLMessageCell ()@property (nonatomic, weak) UILabel *timeView;@property (nonatomic, weak) UIImageView *iconView;@property (nonatomic, weak) UIButton *textView;@end@implementation LLMessageCell+ (instancetype)messageCellWith:(UITableView *)tableView{ static NSString *ID = @"messageCell"; LLMessageCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; if (!cell) { cell = [[LLMessageCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID]; } return cell;}- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{ if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) { // 创建cell子控件 self.backgroundColor = [UIColor clearColor]; // time UILabel *timeView = [[UILabel alloc] init]; [self.contentView addSubview:timeView]; timeView.textAlignment = NSTextAlignmentCenter; timeView.font = LLTIMEFONT; self.timeView = timeView; // icon UIImageView *iconView = [[UIImageView alloc] init]; [self.contentView addSubview:iconView]; self.iconView = iconView; // text UIButton *textView = [[UIButton alloc] init]; [self.contentView addSubview: textView]; textView.titleLabel.font = LLTEXTFONT; textView.titleLabel.numberOfLines = 0; textView.contentEdgeInsets = UIEdgeInsetsMake(LLPADDING, LLPADDING, LLPADDING, LLPADDING); self.textView = textView; } return self;}- (void)setMessageFrame:(LLMessageFrame *)messageFrame{ _messageFrame = messageFrame; // 1,设置数据 [self setDate]; // 2,设置frame [self setSubviewsFrame];}- (void)setDate{ LLMessage *message = self.messageFrame.message; self.timeView.text = message.time; NSString *iconName = message.type == LLMessageTypeMe ? @"me" : @"other"; self.iconView.image = [UIImage imageNamed:iconName]; // 设置图片背景 #warning 设置按钮上label字体方法 [self.textView setTitle:message.text forState:UIControlStateNormal]; if (message.type == LLMessageTypeMe) { [self.textView setBackgroundImage:[UIImage registerImage:@"chat_send_nor"] forState:UIControlStateNormal]; [self.textView setBackgroundImage:[UIImage registerImage:@"chat_send_press_pic"] forState:UIControlStateHighlighted]; [self.textView setTitleColor:[UIColor redColor] forState:UIControlStateNormal]; } else { [self.textView setTitleColor:[UIColor blueColor] forState:UIControlStateNormal]; [self.textView setBackgroundImage:[UIImage registerImage:@"chat_recive_nor"] forState:UIControlStateNormal]; [self.textView setBackgroundImage:[UIImage registerImage:@"chat_recive_press_pic"] forState:UIControlStateHighlighted]; }}- (void)setSubviewsFrame{ self.timeView.frame = self.messageFrame.timeF; self.iconView.frame = self.messageFrame.iconF; self.textView.frame = self.messageFrame.textF;}@end
分类:NSString
#import <Foundation/Foundation.h>#import <UIKit/UIKit.h>@interface NSString (LLNSStringExtension)- (CGSize)textOfSize:(CGSize)maxSize font:(UIFont *)font;@end#import "NSString+LLNSStringExtension.h"@implementation NSString (LLNSStringExtension)- (CGSize)textOfSize:(CGSize)maxSize font:(UIFont *)font{ return [self boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : font} context:nil].size;}@end
UIImage分类
#import <UIKit/UIKit.h>@interface UIImage (LLUIImageExtension)+ (UIImage *)registerImage:(NSString *)imageName;@end#import "UIImage+LLUIImageExtension.h"#import <UIKit/UIKit.h>@implementation UIImage (LLUIImageExtension)+ (UIImage *)registerImage:(NSString *)imageName{ UIImage * image = [UIImage imageNamed:imageName]; return [image stretchableImageWithLeftCapWidth:image.size.width * 0.5 topCapHeight:image.size.height * 0.5];}@end
controller:
#import "ViewController.h"#import "LLMessageFrame.h"#import "LLMessage.h"#import "LLMessageCell.h"@interface ViewController () <UITableViewDataSource, UITableViewDelegate, UITextFieldDelegate>@property (nonatomic, strong) NSMutableArray *messageFrames;@property (weak, nonatomic) IBOutlet UITableView *tableView;@property (weak, nonatomic) IBOutlet UIView *footerView;@property (weak, nonatomic) IBOutlet UITextField *textField;@end@implementation ViewController#pragma mark - 懒加载数据模型- (NSMutableArray *)messageFrames{ if (!_messageFrames) { _messageFrames = [LLMessageFrame messageFrameList]; } return _messageFrames;}- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. // 隐藏分割线 self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; // 取消tableView的点击 self.tableView.allowsSelection = NO; self.tableView.backgroundColor = [UIColor colorWithRed:240/255.0 green:224/255.0 blue:224/255.0 alpha:1.0]; // 监听通知 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(clickTextFiled:) name:UIKeyboardWillChangeFrameNotification object:nil]; // 设置文本框左边内容默认有间距 self.textField.leftView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 8, 0)]; self.textField.leftViewMode = UITextFieldViewModeAlways;}- (void)clickTextFiled:(NSNotification *)noti{ CGRect rect = [noti.userInfo[@"UIKeyboardFrameEndUserInfoKey"] CGRectValue]; CGFloat moveY = rect.origin.y - self.view.frame.size.height; self.view.transform = CGAffineTransformMakeTranslation(0, moveY);}- (void)dealloc{ [[NSNotificationCenter defaultCenter] removeObserver:self];}#pragma mark - 数据源方法- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return self.messageFrames.count;}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ // 1,创建cell LLMessageCell *cell = [LLMessageCell messageCellWith:tableView]; // 2,设置cell cell.messageFrame = self.messageFrames[indexPath.row]; return cell;}#pragma mark - 代理方法- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ return [self.messageFrames[indexPath.row] cellHeight];}- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{ [self.view endEditing:YES];}#pragma mark - 文本框代理方法- (BOOL)textFieldShouldReturn:(UITextField *)textField{ LLMessageFrame *frame = [[LLMessageFrame alloc] init]; LLMessage *message = [[LLMessage alloc] init]; NSDate *date = [NSDate date]; NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; formatter.dateFormat = @"hh:mm"; NSString *time = [formatter stringFromDate:date]; message.time = time; message.text = textField.text; message.type = LLMessageTypeMe; LLMessageFrame *lastMF = [self.messageFrames lastObject]; if ([lastMF.message.time isEqualToString:message.time]) { message.hiddenTime = YES; } frame.message = message; [self.messageFrames addObject:frame]; // 刷新 [self.tableView reloadData]; // 自动上滚 NSIndexPath *path = [NSIndexPath indexPathForRow:self.messageFrames.count - 1 inSection:0]; [self.tableView scrollToRowAtIndexPath:path atScrollPosition:UITableViewScrollPositionBottom animated:YES]; textField.text = nil; return YES;}- (BOOL)prefersStatusBarHidden{ return YES;}@end
效果;
UI基础之UITableView案例QQ聊天界面
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。