博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
关情纸尾-----UIKit基础--QQ自定义布心布局
阅读量:5278 次
发布时间:2019-06-14

本文共 11357 字,大约阅读时间需要 37 分钟。

 

简述整个项目的开发过程

  1.在main.stroybord 中搭建基本界面

  2.创建模型,一个是数据模型,一个是frame模型

  3.实现对cell操作的封装

  4.解决显示时间的细节问题

  5.解决聊天内容的背景问题

  6.用通知机制监听键盘

  7.发送消息

 

一、在main.stroybord 中搭建基本界面

 

二、创建模型,一个是数据模型,一个是frame模型

根据message.plist文件创建模型

数据模型ZLMessage

1 #import 
2 3 4 5 typedef enum { 6 ZLMessageTypeMe = 0, //0表示自己,并且系统默认的 也是0 ,然后递增加1 7 ZLMessageTypeOther 8 }ZLMessageType; 9 10 @interface ZLMessage : NSObject11 12 //时间13 @property (nonatomic, strong) NSString *time;14 15 //内容16 @property (nonatomic, strong)NSString *text;17 18 //类型19 @property (nonatomic, assign)ZLMessageType type;20 21 //是否显示时间22 @property (nonatomic, assign)BOOL hideTime;23 24 +(instancetype)messageWithDict:(NSDictionary *)dict;25 -(instancetype)initWithDict:(NSDictionary *)dict;26 @end

 

#import "ZLMessage.h"@implementation ZLMessage+(instancetype)messageWithDict:(NSDictionary *)dict{    return [[self alloc] initWithDict:dict];}-(instancetype)initWithDict:(NSDictionary *)dict{    if (self = [super init]) {        [self setValuesForKeysWithDictionary:dict];    }    return self;}@end

 

 

 

frame模型ZLMessageFrame

 

#import 
#import "UIKit/UIkit.h"@class ZLMessage;@interface ZLMessageFrame : NSObject// 头像的frame@property (nonatomic, assign, readonly) CGRect iconF;//时间的frame@property (nonatomic, assign, readonly) CGRect timeF;//正文的frame@property (nonatomic, assign, readonly) CGRect textF;//cell的高度@property (nonatomic, assign, readonly) CGFloat cellHeight;//数据模型@property (nonatomic, strong) ZLMessage* message;@end
 

#define ZLTextFont [UIFont systemFontOfSize:15]

 

#import "ZLMessageFrame.h"

 

#import "ZLMessage.h"

@implementation ZLMessageFrame

/**

 *  计算文字尺寸

 *

 *  @param text    需要计算尺寸的文字

 *  @param font    文字的字体

 *  @param maxSize 文字的最大尺寸

 */

 

- (CGSize)sizeWithText:(NSString *)text font:(UIFont *)font maxSize:(CGSize)maxSize

{

    NSDictionary *attrs = @{

NSFontAttributeName : font};

    return [text boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:attrs context:nil].size;

}

-(void)setMessage:(ZLMessage *)message

{

    _message = message;

    //计算头像,正文,时间的Frame

    CGFloat sreenW = [UIScreen mainScreen].bounds.size.width;

    CGFloat padding = 10;    

    //1.时间   CGFloat timeX = 0;

    CGFloat timeY = 0;

    CGFloat timeW = sreenW;

    CGFloat timeH = 40;

    _timeF = CGRectMake(timeX, timeY, timeW, timeH);

     //2.头像

    CGFloat iconY = CGRectGetMaxY(_timeF);

    CGFloat iconW = 40;

    CGFloat iconH = 40;

    CGFloat iconX;

    if (message.type == ZLMessageTypeOther) {

        iconX = padding;

    } else {

        iconX = sreenW - iconW - padding;

    }

    _iconF = CGRectMake(iconX, iconY, iconW, iconH);

    //3.正文

    CGFloat textY = iconY;

    CGFloat textX;

    //文字的尺寸

    CGSize textMaxSize = CGSizeMake(150, MAXFLOAT);

    CGSize textSize = [self sizeWithText:message.text font:ZLTextFont maxSize:textMaxSize];

    if (message.type == ZLMessageTypeOther) {

        textX = CGRectGetMaxX(_iconF) + padding;

    } else {

        textX = iconX - padding - textSize.width;

    }

    _textF = (CGRect){

{textX,textY},textSize};

    //cell 的高度

    CGFloat textMaxY = CGRectGetMaxY(_textF);

    CGFloat iconMaxY = CGRectGetMaxY(_iconF);

   _cellHeight = MAX(textMaxY, iconMaxY) + padding;

}

 

@end

 
- (NSMutableArray *)messagesFrames{    if (_messagesFrames == nil){        //取出路径        NSString *path = [[NSBundle mainBundle] pathForResource:@"messages.plist" ofType:nil];                //取出该路劲下的数组        NSArray *dictArray = [NSArray arrayWithContentsOfFile:path];                NSMutableArray *mfArray = [NSMutableArray array];                //遍历数组形成字典        for (NSDictionary* dict  in dictArray) {            //消息模型            ZLMessage *msg = [ZLMessage messageWithDict:dict];                                    //frame模型            ZLMessageFrame *mgf =[[ZLMessageFrame alloc] init];            mgf.message = msg;                        [mfArray addObject:mgf];        }        _messagesFrames = mfArray;    }        return _messagesFrames;}

 

 

三、实现对cell操作的封装

 

#import 
@class ZLMessageFrame;@interface ZLMessageCell : UITableViewCell+(instancetype) cellWithTableView:(UITableView *)tableView;@property (nonatomic, strong) ZLMessageFrame* messageFrame;@end
#define ZLTextFont [UIFont systemFontOfSize:15]#import "ZLMessageCell.h"#import "ZLMessageFrame.h"#import "ZLMessage.h"@interface ZLMessageCell()//时间@property (nonatomic, weak) UILabel *timeView;//头像@property (nonatomic, weak) UIImageView *iconView;//正文@property (nonatomic, weak) UIButton *textView;;@end@implementation ZLMessageCell+(instancetype) cellWithTableView:(UITableView *)tableView{    static NSString *ID = @"message";    //先从缓存池中取cell    ZLMessageCell *cell = [tableView dequeueReusableCellWithIdentifier:ID ];    //如果缓存池中没有就自己创建cell,并且要带有标记    if (cell == nil) {        cell = [[ZLMessageCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];    }    return cell;}//做一次性的初始化-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];    if (self){                //子控件的创建和初始化        //1.时间        UILabel *timeView = [[UILabel alloc] init];        timeView.textColor = [UIColor grayColor];        timeView.textAlignment = NSTextAlignmentCenter;        timeView.font = [UIFont systemFontOfSize:13];        [self.contentView addSubview:timeView];        self.timeView = timeView;                //2.头像        UIImageView *iconView = [[UIImageView alloc] init];        //iconView.backgroundColor = [UIColor redColor];        [self.contentView addSubview:iconView];        self.iconView = iconView;                //3.正文        UIButton *textView = [[UIButton alloc] init];        textView.titleLabel.numberOfLines = 0;//自动换行        textView.backgroundColor = [UIColor purpleColor];        textView.titleLabel.font = ZLTextFont;        [self.contentView addSubview:textView];        self.textView = textView;            }    return self;}-(void)setMessageFrame:(ZLMessageFrame *)messageFrame{    _messageFrame = messageFrame;    ZLMessage *message = messageFrame.message;        //时间    self.timeView.text = message.time;    self.timeView.frame = messageFrame.timeF;        //头像    NSString *icon = (message.type == ZLMessageTypeMe) ? @"me" : @"other";    self.iconView.image = [UIImage imageNamed:icon];    self.iconView.frame = messageFrame.iconF;            //正文    [self.textView setTitle:message.text forState:UIControlStateNormal];    self.textView.frame = messageFrame.textF;}@end

 

 

 

四、解决显示时间的细节问题

 如果时间是一样的,就只显示一个时间

在ZLMessage.h文件中添加属性//是否显示时间@property (nonatomic, assign)BOOL hideTime;
在控制器.m文件中添加代码,即取出上一个模型和刚刚添加的模型的时间作比较,如果时间一样,就只显示上一个模型的time数据//遍历数组形成字典        for (NSDictionary* dict  in dictArray) {            //消息模型            ZLMessage *msg = [ZLMessage messageWithDict:dict];                        //取出上一个模型            ZLMessageFrame *lastMf = [mfArray lastObject];            ZLMessage *lastMg = lastMf.message;                        msg.hideTime = [msg.time isEqualToString:lastMg.

 

 五、解决聊天内容的背景问题

//设置图片if (message.type == MJMessageTypeMe) { // 自己发的,蓝色        [self.textView setBackgroundImage:[UIImage resizableImage:@"chat_send_nor"] forState:UIControlStateNormal];    } else { // 别人发的,白色        [self.textView setBackgroundImage:[UIImage resizableImage:@"chat_recive_nor"] forState:UIControlStateNormal];    }
//为了显示对话框背景图,需要设置正文按钮的内边距        textView.contentEdgeInsets = UIEdgeInsetsMake(ZLTextPadding, ZLTextPadding, ZLTextPadding, ZLTextPadding);
//文字计算的最大尺寸    CGSize textMaxSize = CGSizeMake(150, MAXFLOAT);//文字计算出来的真实尺寸(显示文字的尺寸)    CGSize textSize = [self sizeWithText:message.text font:ZLTextFont maxSize:textMaxSize]; //按钮最终的尺寸       CGSize textBtnSize = CGSizeMake(textSize.width +ZLTextPadding *2, textSize.height +ZLTextPadding *2);        if (message.type == ZLMessageTypeOther) {        textX = CGRectGetMaxX(_iconF) + padding;    } else {        textX = iconX - padding - textBtnSize.width;    }//    _textF = CGRectMake(textX, textY, textSize.width +40, textSize.height +40);    _textF = (CGRect){
{textX,textY},textBtnSize};

 

 

六、用通知机制监听键盘

首先介绍一下通知机制

 

 

 

 

 

 

 

代码如下:

 

// 监听键盘的通知    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil];//取消监听- (void)dealloc{    [[NSNotificationCenter defaultCenter] removeObserver:self];}/** *  当键盘改变了frame(位置和尺寸)的时候调用 */- (void)keyboardWillChangeFrame:(NSNotification *)note{    // 设置窗口的颜色    self.view.window.backgroundColor = self.tableView.backgroundColor;        // 0.取出键盘动画的时间    CGFloat duration = [note.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];        // 1.取得键盘最后的frame    CGRect keyboardFrame = [note.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];        // 2.计算控制器的view需要平移的距离    CGFloat transformY = keyboardFrame.origin.y - self.view.frame.size.height;        // 3.执行动画    [UIView animateWithDuration:duration animations:^{        self.view.transform = CGAffineTransformMakeTranslation(0, transformY);    }];}

 

 

7.发送消息

 

//监听文本框#import "MJViewController.h"#import "MJMessage.h"#import "MJMessageFrame.h"#import "MJMessageCell.h"@interface MJViewController () 
@property (weak, nonatomic) IBOutlet UITableView *tableView;@property (nonatomic, strong) NSMutableArray *messageFrames;@property (weak, nonatomic) IBOutlet UITextField *inputView;@property (nonatomic, strong) NSDictionary *autoreply;@end@implementation MJViewController- (void)viewDidLoad{ [super viewDidLoad]; // 1.表格的设置 // 去除分割线 self.tableView.backgroundColor = [UIColor colorWithRed:235/255.0 green:235/255.0 blue:235/255.0 alpha:1.0]; self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; self.tableView.allowsSelection = NO; // 不允许选中 self.tableView.delegate = self; // 2.监听键盘的通知 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil]; // 3.设置文本框左边显示的view self.inputView.leftView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 8, 0)]; // 永远显示 self.inputView.leftViewMode = UITextFieldViewModeAlways; self.inputView.delegate = self;}/** * 发送一条消息 */- (void)addMessage:(NSString *)text type:(MJMessageType)type{ // 1.数据模型 MJMessage *msg = [[MJMessage alloc] init]; msg.type = type; msg.text = text; // 设置数据模型的时间 NSDate *now = [NSDate date]; NSDateFormatter *fmt = [[NSDateFormatter alloc] init]; fmt.dateFormat = @"HH:mm"; // NSDate ---> NSString // NSString ---> NSDate // fmt.dateFormat = @"yyyy-MM-dd HH:mm:ss"; // 2014-08-09 15:45:56 // 09/08/2014 15:45:56 msg.time = [fmt stringFromDate:now]; // 看是否需要隐藏时间 MJMessageFrame *lastMf = [self.messageFrames lastObject]; MJMessage *lastMsg = lastMf.message; msg.hideTime = [msg.time isEqualToString:lastMsg.time]; // 2.frame模型 MJMessageFrame *mf = [[MJMessageFrame alloc] init]; mf.message = msg; [self.messageFrames addObject:mf]; // 3.刷新表格 [self.tableView reloadData]; // 4.自动滚动表格到最后一行 NSIndexPath *lastPath = [NSIndexPath indexPathForRow:self.messageFrames.count - 1 inSection:0]; [self.tableView scrollToRowAtIndexPath:lastPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];}/** * 根据自己发的内容取得自动回复的内容 * * @param text 自己发的内容 */- (NSString *)replayWithText:(NSString *)text{ for (int i = 0; i

 

 

 

最终界面如图:

 

 

学的不精,笔记做的不好,见谅见谅。。。。。。。

 

转载于:https://www.cnblogs.com/Lorraine1/p/5766054.html

你可能感兴趣的文章
Learning Python 009 dict(字典)和 set
查看>>
JavaScript中随着鼠标拖拽而移动的块
查看>>
HDU 1021 一道水题
查看>>
The operation couldn’t be completed. (LaunchServicesError error 0.)
查看>>
php每天一题:strlen()与mb_strlen()的作用分别是什么
查看>>
工作中收集JSCRIPT代码之(下拉框篇)
查看>>
《转载》POI导出excel日期格式
查看>>
code异常处理
查看>>
git - 搭建最简单的git server
查看>>
会话控制
查看>>
推荐一款UI设计软件Balsamiq Mockups
查看>>
Linux crontab 命令格式与详细例子
查看>>
百度地图Api进阶教程-地图鼠标左右键操作实例和鼠标样式6.html
查看>>
游标使用
查看>>
LLBL Gen Pro 设计器使用指南
查看>>
SetCapture() & ReleaseCapture() 捕获窗口外的【松开左键事件】: WM_LBUTTONUP
查看>>
Android 设置界面的圆角选项
查看>>
百度地图api服务端根据经纬度得到地址
查看>>
CSS中隐藏内容的3种方法及属性值
查看>>
每天一个linux命令(1):ls命令
查看>>