iOS UI-QQ聊天布局

 

一、Model

BWMessage.h

#import <Foundation/Foundation.h>

typedef enum{
    BWMessageMe    = 0,//表示自己
    BWMessageOther = 1 //表示对方
}BWMessageType;

@interface BWMessage : NSObject
//消息正文
@property(nonatomic, copy)   NSString *text;
//消息时间
@property(nonatomic, copy)   NSString *time;
//消息类型
@property(nonatomic, assign) BWMessageType type;

//记录是否隐藏时间
@property(nonatomic, assign) BOOL hideTime;

- (instancetype)initWithDict:(NSDictionary *)dict;
+ (instancetype)messageWithDict:(NSDictionary *)dict;

@end


#import "BWMessage.h"

@implementation BWMessage

- (instancetype)initWithDict:(NSDictionary *)dict
{
    if (self = [super init]) {
//        _text = dict[@"text"];
//        _time = dict[@"time"];
//        _type =(BWMessageType)dict[@"type"];
        [self setValuesForKeysWithDictionary:dict];
    }
    return self;
}

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

@end

BWMessageFrame.h

 1 #import <Foundation/Foundation.h>
 2 #import <CoreGraphics/CoreGraphics.h>
 3 
 4 #define textFont [UIFont systemFontOfSize:16]
 5 
 6 @class BWMessage;
 7 
 8 @interface BWMessageFrame : NSObject
 9 
10 @property (nonatomic, strong) BWMessage *message;
11 @property (nonatomic, assign, readonly) CGRect timeFrame;
12 @property (nonatomic, assign, readonly) CGRect iconFrame;
13 @property (nonatomic, assign, readonly) CGRect textFrame;
14 
15 @property (nonatomic, assign, readonly) CGFloat rowHeight;
16 
17 @end
18 
19 
20 #import "BWMessageFrame.h"
21 #import <UIKit/UIKit.h>
22 #import "BWMessage.h"
23 #import "NSString+BWTextSize.h"
24 
25 @implementation BWMessageFrame
26 
27 //重写setMessage
28 - (void)setMessage:(BWMessage *)message
29 {
30     _message = message;
31     
32     //计算每个控件的Frame
33     
34     //设置统一的间距
35     CGFloat margin = 5;
36     //获取屏幕的宽度
37     CGFloat screenW = [UIScreen mainScreen].bounds.size.width;
38     //计算时间label的frame
39     CGFloat timeX = 0;
40     CGFloat timeY = 0;
41     CGFloat timeW = screenW;
42     CGFloat timeH = 15;
43     
44     if (!message.hideTime) {
45         //如果需要时间Label,那么再计算frame
46         _timeFrame = CGRectMake(timeX, timeY, timeW, timeH);
47     }
48     
49     //计算头像的frame
50     CGFloat iconW = 30;
51     CGFloat iconH = 30;
52     CGFloat iconY = CGRectGetMaxY(_timeFrame);
53     CGFloat iconX = message.type == BWMessageOther ? margin : screenW - iconW - margin;
54     _iconFrame = CGRectMake(iconX, iconY, iconW, iconH);
55     
56     //计算正文的frame
57     CGSize textSize = [message.text sizeOfTextWithMaxsize:CGSizeMake(250, MAXFLOAT) andFont:textFont];
58     CGFloat textW = textSize.width+40;
59     CGFloat textH = textSize.height+30;
60     CGFloat textY = iconY;
61     CGFloat textX = message.type == BWMessageOther ? CGRectGetMaxX(_iconFrame) : screenW - margin - iconW - textW;
62     _textFrame = CGRectMake(textX, textY, textW, textH);
63     
64     //计算行高
65     //获取 头像的最大Y值和正文的最大Y值,然后用最大Y值+margin
66     CGFloat maxY = MAX(CGRectGetMaxY(_iconFrame), CGRectGetMaxY(_textFrame));
67     _rowHeight = maxY + margin;
68     
69     
70 }
71 
72 @end

NSString+BWTextSize.h

 1 //  NSString+BWTextSize.h
 2 //  IOS_QQ聊天
 3 //
 4 //  Created by ma c on 16/1/10.
 5 //  Copyright (c) 2016年 博文科技. All rights reserved.
 6 //
 7 
 8 #import <Foundation/Foundation.h>
 9 #import <UIKit/UIKit.h>
10 @interface NSString (BWTextSize)
11 
12 //对象方法-计算文本尺寸
13 - (CGSize)sizeOfTextWithMaxsize:(CGSize)maxSize andFont:(UIFont *)font;
14 
15 //类方法-计算文本尺寸
16 + (CGSize)sizeWithText:(NSString *)text andMaxSize:(CGSize)maxSize andFont:(UIFont *)font;
17 
18 @end
19 
20 //  NSString+BWTextSize.m
21 //  IOS_QQ聊天
22 //
23 //  Created by ma c on 16/1/10.
24 //  Copyright (c) 2016年 博文科技. All rights reserved.
25 //
26 
27 #import "NSString+BWTextSize.h"
28 
29 @implementation NSString (BWTextSize)
30 
31 
32 - (CGSize)sizeOfTextWithMaxsize:(CGSize)maxSize andFont:(UIFont *)font
33 {
34     NSDictionary *attr = @{NSFontAttributeName : font};
35     return [self boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:attr context:nil].size;
36 }
37 
38 + (CGSize)sizeWithText:(NSString *)text andMaxSize:(CGSize)maxSize andFont:(UIFont *)font
39 {
40     return [text sizeOfTextWithMaxsize:maxSize andFont:font];
41 }
42 
43 @end

 

三、View

  1 //  BWMessageCell.h
  2 //  IOS_QQ聊天
  3 //
  4 //  Created by ma c on 16/1/10.
  5 //  Copyright (c) 2016年 博文科技. All rights reserved.
  6 //
  7 
  8 #import <UIKit/UIKit.h>
  9 @class BWMessageFrame;
 10 
 11 @interface BWMessageCell : UITableViewCell
 12 
 13 @property (nonatomic, strong) BWMessageFrame *messageFrame;
 14 
 15 + (instancetype) messageCellWithTableView:(UITableView *)tableView;
 16 
 17 @end
 18 
 19 //  BWMessageCell.m
 20 //  IOS_QQ聊天
 21 //
 22 //  Created by ma c on 16/1/10.
 23 //  Copyright (c) 2016年 博文科技. All rights reserved.
 24 //
 25 
 26 #import "BWMessageCell.h"
 27 #import "BWMessage.h"
 28 #import "BWMessageFrame.h"
 29 
 30 @interface BWMessageCell ()
 31 
 32 @property (nonatomic, strong) UILabel *lblTime;
 33 @property (nonatomic, strong) UIImageView *imgViewHead;
 34 @property (nonatomic, strong) UIButton *btnText;
 35 
 36 @end
 37 
 38 @implementation BWMessageCell
 39 
 40 //创建自定义Cell
 41 + (instancetype)messageCellWithTableView:(UITableView *)tableView
 42 {
 43     NSString *cellIdentifier = @"cellIdentifier";
 44     BWMessageCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
 45     if (!cell) {
 46         cell = [[BWMessageCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
 47     }
 48     //设置单元格的背景颜色
 49     cell.backgroundColor = [UIColor clearColor];
 50     return cell;
 51 }
 52 
 53 #pragma mark - 重写initWithStyle的方法
 54 - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
 55 {
 56     if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
 57         //创建子控件
 58         
 59         //显示时间的label
 60         self.lblTime = [[UILabel alloc] init];
 61         self.lblTime.textAlignment = NSTextAlignmentCenter;
 62         self.lblTime.font = [UIFont systemFontOfSize:14];
 63         [self.contentView addSubview:self.lblTime];
 64         
 65         //显示头像的UIImageView
 66         self.imgViewHead = [[UIImageView alloc] init];
 67         [self.contentView addSubview:self.imgViewHead];
 68         
 69         //显示正文的按钮
 70         self.btnText = [[UIButton alloc] init];
 71         self.btnText.titleLabel.font = textFont;
 72         [self.btnText setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
 73         self.btnText.titleLabel.numberOfLines = 0;
 74         //self.btnText.backgroundColor = [UIColor purpleColor];
 75         //self.btnText.titleLabel.backgroundColor = [UIColor redColor];
 76         
 77         //设置按钮的内边距
 78         self.btnText.contentEdgeInsets = UIEdgeInsetsMake(15, 20, 15, 20);
 79         [self.contentView addSubview:self.btnText];
 80     }
 81     return self;
 82 }
 83 #pragma mark - 重写setMessageFrame的方法
 84 - (void)setMessageFrame:(BWMessageFrame *)messageFrame
 85 {
 86     _messageFrame = messageFrame;
 87     
 88     //获取数据模型
 89     BWMessage *message = messageFrame.message;
 90     
 91     //分别设置控件的数据和frame
 92     
 93     //设置时间的内容和frame
 94     self.lblTime.text = message.time;
 95     self.lblTime.frame = messageFrame.timeFrame;
 96     self.lblTime.hidden = message.hideTime;
 97     
 98     //设置头像的图片和frame
 99     //根据消息类型,判断应该使用哪张图片
100     NSString *iconImg = message.type == BWMessageMe ? @"me" : @"other";
101     self.imgViewHead.image = [UIImage imageNamed:iconImg];
102     self.imgViewHead.frame = messageFrame.iconFrame;
103     
104     //设置正文的内容和frame
105     [self.btnText setTitle:message.text forState:UIControlStateNormal];
106     self.btnText.frame = messageFrame.textFrame;
107     
108     //设置正文的背景图
109     NSString *imgNor,*imgHighlighted;
110     if (message.type == BWMessageMe) {
111         //自己发送的消息
112         imgNor = @"chat_send_nor";
113         imgHighlighted = @"chat_send_press_pic";
114         //设置消息字体的颜色
115         [self.btnText setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
116     }
117     else{
118         //对方发送的消息
119         imgNor = @"chat_recive_nor";
120         imgHighlighted = @"chat_recive_press_pic";
121         //设置消息的字体颜色
122         [self.btnText setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
123     }
124     //加载图片
125     UIImage *imageNor = [UIImage imageNamed:imgNor];
126     UIImage *imageHighlighted = [UIImage imageNamed:imgHighlighted];
127     
128     //用平铺的方式拉伸图片
129     imageNor = [imageNor stretchableImageWithLeftCapWidth:imageNor.size.width/2 topCapHeight:imageNor.size.height/2];
130     imageHighlighted = [imageHighlighted stretchableImageWithLeftCapWidth:imageHighlighted.size.width/2 topCapHeight:imageHighlighted.size.height/2];
131     
132     //设置背景图
133     [self.btnText setBackgroundImage:imageNor forState:UIControlStateNormal];
134     [self.btnText setBackgroundImage:imageHighlighted forState:UIControlStateHighlighted];
135     
136 }
137 
138 - (void)awakeFromNib {
139     // Initialization code
140 }
141 
142 - (void)setSelected:(BOOL)selected animated:(BOOL)animated {
143     [super setSelected:selected animated:animated];
144 
145     // Configure the view for the selected state
146 }
147 
148 @end

三、Controller

  1 //  ViewController.m
  2 //  IOS_QQ聊天
  3 //
  4 //  Created by ma c on 16/1/9.
  5 //  Copyright (c) 2016年 博文科技. All rights reserved.
  6 //
  7 
  8 #import "ViewController.h"
  9 #import "BWMessage.h"
 10 #import "BWMessageFrame.h"
 11 #import "BWMessageCell.h"
 12 
 13 @interface ViewController ()<UITableViewDataSource,UITableViewDelegate,UITextFieldDelegate>
 14 //消息的Frame模型对象
 15 @property (nonatomic, strong) NSMutableArray *arrMessageFrame;
 16 
 17 @property (weak, nonatomic) IBOutlet UITableView *tableView;
 18 @property (weak, nonatomic) IBOutlet UITextField *textInput;
 19 
 20 @end
 21 
 22 @implementation ViewController
 23 
 24 #pragma mark - 文本框代理方法
 25 
 26 //return键被单击的时候触发
 27 - (BOOL)textFieldShouldReturn:(UITextField *)textField
 28 {
 29     //1.获取用户输入的文本
 30     NSString *text = textField.text;
 31     
 32     //2.发送用户的消息
 33     [self sendMessage:text withType:BWMessageMe];
 34     
 35     //3.发送系统的消息
 36     [self sendMessage:@"不认识" withType:BWMessageOther];
 37 
 38     //4.清空文本框
 39     textField.text = nil;
 40     
 41        return YES;
 42 }
 43 //发送消息
 44 - (void)sendMessage:(NSString *)msg withType:(BWMessageType)type
 45 {
 46     //1.创建一个数据模型和frame模型
 47     //数据模型
 48     BWMessage *model = [[BWMessage alloc] init];
 49     //获取当前系统时间
 50     NSDate *nowDate = [NSDate date];
 51     //创建一个日期格式化器
 52     NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
 53     //设置格式
 54     formatter.dateFormat = @"今天:HH:mm";
 55     //进行日期的格式化
 56     model.time = [formatter stringFromDate:nowDate];
 57     model.type = type;
 58     model.text = msg;
 59     
 60     //frame模型
 61     BWMessageFrame *frameModel = [[BWMessageFrame alloc] init];
 62     frameModel.message = model;
 63     //根据当前的消息时间和上一条消息的时间,来设置是否隐藏时间Label
 64     BWMessageFrame *lastMessageFrame = [self.arrMessageFrame lastObject];
 65     NSString *lastTime = lastMessageFrame.message.time;
 66     if ([model.time isEqualToString:lastTime]) {
 67         model.hideTime = YES;
 68     }
 69     
 70     //2.把frame模型加载到集合中
 71     [self.arrMessageFrame addObject:frameModel];
 72     
 73     //3.刷新UITableView数据
 74     [self.tableView reloadData];
 75     
 76     //4.把最后一行滚动到最上面
 77     NSIndexPath *lastIndexPath = [NSIndexPath indexPathForRow:self.arrMessageFrame.count - 1 inSection:0];
 78     [self.tableView scrollToRowAtIndexPath:lastIndexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
 79 }
 80 
 81 
 82 #pragma mark - 滚动视图代理方法
 83 - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
 84 {
 85     //[self.textInput resignFirstResponder];
 86     //滚动把键盘叫回去
 87     [self.view endEditing:YES];
 88 }
 89 
 90 #pragma mark - 数据源方法
 91 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
 92 {
 93     return 1;
 94 }
 95 
 96 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
 97 {
 98     return self.arrMessageFrame.count;
 99 }
100 
101 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
102 {
103     //1.获取模型数据
104     BWMessageFrame *frameModel = self.arrMessageFrame[indexPath.row];
105     //2.创建单元格
106     BWMessageCell *cell = [BWMessageCell messageCellWithTableView:tableView];
107     //3.把模型赋值给单元格
108     cell.messageFrame = frameModel;
109     //4.返回单元格
110     return cell;
111 }
112 
113 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
114 {
115     BWMessageFrame *frameModel = self.arrMessageFrame[indexPath.row];
116     return frameModel.rowHeight;
117 }
118 
119 #pragma mark - 懒加载
120 - (NSMutableArray *)arrMessageFrame
121 {
122     if (_arrMessageFrame == nil) {
123         
124         NSString *path = [[NSBundle mainBundle] pathForResource:@"messages.plist" ofType:nil];
125         
126         NSArray *arrDict = [NSArray arrayWithContentsOfFile:path];
127         NSMutableArray *arrModel = [NSMutableArray array];
128         
129         for (NSDictionary *dict in arrDict) {
130             //创建一个数据模型
131             BWMessage *dataModel = [BWMessage messageWithDict:dict];
132             //创建一个Frame模型
133             BWMessageFrame *modelFrame = [[BWMessageFrame alloc] init];
134             
135             //获取上一个数据模型
136             BWMessage *lastMessage = (BWMessage *)[[arrModel lastObject] message];
137             //判断“当前的模型时间”是否和“上一个模型时间”一样
138             if ([dataModel.time isEqualToString:lastMessage.time]) {
139                 dataModel.hideTime = YES;
140             }
141             else
142             {
143                 dataModel.hideTime = NO;
144             }
145             
146             modelFrame.message = dataModel;
147         
148             //把Frame模型加载到arrModel模型数组中
149             [arrModel addObject:modelFrame];
150         }
151         _arrMessageFrame = arrModel;
152     }
153     return _arrMessageFrame;
154 }
155 
156 #pragma mark - 视图加载
157 - (void)viewDidLoad {
158     [super viewDidLoad];
159     //取消分割线
160     self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
161     //设置TableView的背景色
162     self.tableView.backgroundColor = [UIColor colorWithRed:236.0/255 green:236.0/255 blue:236.0/255 alpha:1];
163     //设置TableView的行不允许被选中
164     self.tableView.allowsSelection = NO;
165     //设置文本框距离最左侧有一段距离
166     UIView *leftView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 5, 1)];
167     //把leftView设置给文本框
168     self.textInput.leftView = leftView;
169     self.textInput.leftViewMode = UITextFieldViewModeWhileEditing;
170     
171     //监听键盘的弹出事件
172     //1.创建一个NSNotificationCenter对象
173     NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
174     //2.监听键盘弹出发出的通知
175     [center addObserver:self selector:@selector(keyboardWillChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil];
176     
177 }
178 //通知关联方法
179 - (void)keyboardWillChangeFrame:(NSNotification *)noteInfo
180 {
181 //    NSLog(@"通知的名称:%@",noteInfo.name);
182 //    NSLog(@"通知的发布者:%@",noteInfo.object);
183 //    NSLog(@"通知的内容:%@",noteInfo.userInfo);
184     //1.获取键盘显示完毕或者隐藏完毕后的Y值
185     CGRect rectEnd = [noteInfo.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
186     CGFloat keyboardY = rectEnd.origin.y;
187     //用键盘的Y值减去屏幕的高度计算平移的值
188     CGFloat transformValue = keyboardY - self.view.frame.size.height;
189     
190     [UIView animateWithDuration:0.25 animations:^{
191         
192         self.view.transform = CGAffineTransformMakeTranslation(0, transformValue);
193     }];
194     
195     //让UITableView的最后一行滚动到最上面
196     NSIndexPath *lastRowindexPath = [NSIndexPath indexPathForRow:self.arrMessageFrame.count - 1 inSection:0];
197     [self.tableView scrollToRowAtIndexPath:lastRowindexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
198 }
199 
200 - (void)dealloc
201 {
202     [[NSNotificationCenter defaultCenter] removeObserver:self];
203 }
204 
205 - (BOOL)prefersStatusBarHidden
206 {
207     return YES;
208 }
209 
210 - (void)didReceiveMemoryWarning {
211     [super didReceiveMemoryWarning];
212     // Dispose of any resources that can be recreated.
213 }
214 
215 @end

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值