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
  • 相关阅读:
    linux 命令——19 find (转)
    linux 命令——18 locate (转)
    linux 命令——17 whereis(转)
    linux 命令——16 which(转)
    linux 命令——15 tail (转)
    linux 命令——14 head (转)
    Java for LeetCode 038 Count and Say
    Java for LeetCode 037 Sudoku Solver
    Java for LeetCode 036 Valid Sudoku
    Java for LeetCode 035 Search Insert Position
  • 原文地址:https://www.cnblogs.com/oc-bowen/p/5119662.html
Copyright © 2011-2022 走看看