zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    软件工程——结构化方法
    静态变量的坑
    OpenCV中对Mat的遍历访问与赋值
    SQL SERVER 自定义函数 整数转成指定长度的16进制 转换成指定长度的16进制 不足补0
    Ext.Net中的Task控件的使用
    字符集越界 正则表达式匹配车牌
    [TOEIC] 2013年12月25日托业考试总结
    WebKit 内容整理
    [C#/.NET]how to implement web application localization in .net 4.0
    C# 代码为什么比 C++代码 编译速度快?
  • 原文地址:https://www.cnblogs.com/oc-bowen/p/5119662.html
Copyright © 2011-2022 走看看