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);}// iconCGFloat 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);// textCGFloat 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];// timeUILabel *timeView = [[UILabel alloc] init];[self.contentView addSubview:timeView];timeView.textAlignment = NSTextAlignmentCenter;timeView.font = LLTIMEFONT;self.timeView = timeView;// iconUIImageView *iconView = [[UIImageView alloc] init];[self.contentView addSubview:iconView];self.iconView = iconView;// textUIButton *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,创建cellLLMessageCell *cell = [LLMessageCell messageCellWith:tableView];// 2,设置cellcell.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
效果;
转载于:https://www.cnblogs.com/-boy/p/4133663.html
UI基础之UITableView案例QQ聊天界面相关推荐
- C语言实现类似QQ聊天界面抖动功能
该博文为原创文章,未经博主同意不得转载,如同意转载请注明博文出处 本文章博客地址:https://cplusplus.blog.csdn.net/article/details/104991863 实 ...
- 点击跳转到QQ聊天界面
<!--//需要添加好友验证--><a href="tencent://message/?uin=QQ号码&Site=&Menu=yes"> ...
- gui编程实践(2)--qq聊天界面 JTextArea多行文本框组件
//qq聊天界面 package com.test; import java.awt.*; import javax.swing.*; public class Demo8_10 extends JF ...
- 【3】QQ 聊天界面
1.说明 稍微修改了下QQ示例里面的聊天界面界面,然后把代码扣过来完成了QQ聊天界面部分,效果还可以. 不过自己添加了消息响应:窗口抖动,截屏,字体栏的显示和隐藏 2.代码部分 // QQTalk.h ...
- qt小项目 代码实现简易的QQ聊天界面
qt小项目 代码实现简易的QQ聊天界面 代码 效果图 总结 代码 myDialog.h #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QW ...
- QQ聊天界面的布局和设计(IOS篇)-第二季
QQChat Layout - 第二季 本来第二季是快写好了, 也花了点功夫, 结果gitbook出了点问题, 给没掉了.有些细节可能会一带而过, 如有疑问, 相互交流进步~. 在第一季中我们完成了Q ...
- 防qq聊天界面纯HTML5,html5 实现qq聊天的气泡效果
教程:http://m.blog.csdn.net/blog/yhc13429826359/38778337 写的很好.自己实现的时候,由于img float:left,会脱离文档流,导致结构混乱. ...
- UI界面编写(仿QQ聊天界面)
UI界面编写实战 这里我们模拟QQ聊天的主界面,编写一个简单的聊天界面. 项目描述 首先搭建我们的主界面,在最上边放一个标题栏,然后是一个ListView,用于展示发送的消息,最下边是选择要发送的表情 ...
- android布局基础及范例:QQ登陆界面设计
使用android手机的用户想必都有android手机QQ客户端吧,我们是不是觉得QQ登陆界面非常漂亮美观而且具有亲和力?我们是不是也想作出像 QQ那样美观的界面?有的人肯定会问,做UI那不是美工人员 ...
最新文章
- Win10 + ubuntu16双系统安装以及cuda,cudnn安装
- Android与JS混编(js调用android相机扫描二维码)
- office软件的发展前景_2018年办公软件产业发展趋势
- python 两个乘号是什么_(2)Python 变量和运算符
- 2021年中国大学生程序设计竞赛 女生专场 - 热身赛 Problem C. 口算训练(质因子分解)
- 吉林省统考计算机英语作文,2019年吉林省学位英语作文必背范文(我最……的题材) - 希赛网...
- 515Nod 1126 求递推序列的第n项【矩阵快速幂】
- (三)Java中的HashMap与HashTable的区别
- 疑似Bug:简书安卓10.7首页搜索关键字屏蔽敏感词不彻底
- 荔枝派Nano 全流程指南
- Anaconda 踩过的一些坑
- 叉乘点乘混合运算公式_七(上)数学:有理数混合运算常考题型笔记100%整理,收藏+学习...
- 5月31日武汉国金天地亮灯仪式鎏光绽放!
- chrome 打包安装插件
- LeetCode 319 灯泡开关[数学] HERODING的LeetCode之路
- linux Xinetd服务简介
- word表格分页时怎样能自动生成表头
- Android 仿朋友圈,文字图片视频多条目,自动播放暂停
- 目标检测算法中ROI提取方法比较+源码分析
- [MySQL数据库]-基础多表练习题---员工工资
热门文章
- 连接目标数据库+无恢复目录连接目标数据库+使用有恢复目录连接目标数据库+注册数据库+目录同步+取消目标数据库的连接...
- BZOJ2301: [HAOI2011]Problem b[莫比乌斯反演 容斥原理]【学习笔记】
- 小试牛刀:文本处理工具之grep、egrep详解
- 后续:为LAMP添加XCache加速。
- 利用ping/ipconfig/nslookup/dig/whois简单工具测试DNS
- css3中的渐变效果及花斑动画的实现
- Navigator对象
- Js中RegExp对象
- 想唱你就唱卡拉ok_如何将电唱机与其他设备连接起来
- 开源 三层模型_开源模型将如何超越其他模型