• iOS 聊天界面


                                            

    1 #import <UIKit/UIKit.h>
    2 
    3 @interface AppDelegate : UIResponder <UIApplicationDelegate>
    4 
    5 @property (strong, nonatomic) UIWindow *window;
    6 
    7 
    8 @end
     1 #import "AppDelegate.h"
     2 #import "YXYCViewController.h"
     3 @interface AppDelegate ()
     4 
     5 @end
     6 
     7 @implementation AppDelegate
     8 
     9 
    10 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    11     self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    12     // Override point for customization after application launch.
    13     self.window.backgroundColor = [UIColor whiteColor];
    14     
    15     self.window.rootViewController = [[YXYCViewController alloc] init];
    16     
    17     [self.window makeKeyAndVisible];
    18     return YES;
    19 }
    20 
    21 @end
    1 #import <UIKit/UIKit.h>
    2 
    3 @interface YXYCViewController : UIViewController
    4 
    5 @end
      1 #import "YXYCViewController.h"
      2 #import "YXYCChatUser.h"
      3 #import "YXYCChatTableViewDataSource.h"
      4 #import <QuartzCore/QuartzCore.h>
      5 #import "YXYCChatTableView.h"
      6 #import "YXYCChatData.h"
      7 #define lineHeight 16.0f
      8 #define scale [UIScreen mainScreen].bounds.size.width/320.0
      9 @interface YXYCViewController ()<YXYCChatTableViewDataSource,UITextViewDelegate>
     10 {
     11     UIView *textInputView;
     12     UITextField *textField;
     13     NSMutableArray *Chats;
     14     
     15     UIView *sendView;
     16     UIButton *sendButton;
     17     UITextView *msgText;
     18     BOOL composing;
     19     float prevLines;
     20     YXYCChatUser *me;
     21     YXYCChatUser *you;
     22     //键盘的高度
     23     float keyboardHeight;
     24 }
     25 @property (strong, nonatomic) YXYCChatTableView *chatTable;
     26 @end
     27 
     28 @implementation YXYCViewController
     29 
     30 CGRect appFrame;
     31 - (void)viewDidLoad {
     32     [super viewDidLoad];
     33     // 添加监听
     34     [self addNotification];
     35     // 设置背景颜色
     36     self.view.backgroundColor = [UIColor lightGrayColor];
     37     // 初始化tableView
     38     [self setupTableView];
     39     // 初始化view和textView
     40     [self setupUIViewAndUITextView];
     41     // 初始化sendButton
     42     [self setupSendButton];
     43     // 加载数据
     44     [self loadData];
     45     
     46 }
     47 // 初始化YXYCChatTableView
     48 - (void)setupTableView
     49 {
     50     appFrame = [[UIScreen mainScreen] bounds];
     51     // 创建一个self.chatTable(YXYCChatTableView类型)
     52     self.chatTable = [[YXYCChatTableView alloc] initWithFrame:CGRectMake(0, 40, [[UIScreen mainScreen] bounds].size.width, [[UIScreen mainScreen] bounds].size.height - 40) style:UITableViewStylePlain];
     53     // 设置self.chatTable的背景颜色
     54     self.chatTable.backgroundColor = [UIColor whiteColor];
     55     [self.view addSubview:self.chatTable];
     56 }
     57 // 初始化sendView和msgText
     58 - (void)setupUIViewAndUITextView
     59 {
     60     // 初始化sendView
     61     sendView = [[UIView alloc] initWithFrame:CGRectMake(0, appFrame.size.height-56, appFrame.size.width, 56)];
     62     sendView.backgroundColor = [UIColor blueColor];
     63     sendView.alpha = 0.9;
     64     // 初始化msgText
     65     msgText = [[UITextView alloc] initWithFrame:CGRectMake(7, 10, 225*scale, 36)];
     66     msgText.backgroundColor = [UIColor whiteColor];
     67     msgText.textColor = [UIColor blackColor];
     68     msgText.font = [UIFont boldSystemFontOfSize:12];
     69     // 自动调整与父视图的位置 UIViewAutoresizingFlexibleHeight 自动调整自己的高度,保证与superView顶部和底部的距离不变;UIViewAutoresizingFlexibleTopMargin 自动调整与superView顶部的距离,保证与superView底部的距离不变。
     70     msgText.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleTopMargin;
     71     // 设置圆角半径
     72     msgText.layer.cornerRadius = 10.0f;
     73     // 设置键盘返回键的类型
     74     msgText.returnKeyType = UIReturnKeySend;
     75     msgText.showsHorizontalScrollIndicator = NO;
     76     msgText.showsVerticalScrollIndicator = NO;
     77     // 设置UITextView代理
     78     msgText.delegate = self;
     79     [sendView addSubview:msgText];
     80     msgText.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
     81     [self.view addSubview:sendView];
     82 }
     83 // 初始化sendButton
     84 - (void)setupSendButton
     85 {
     86     sendButton = [[UIButton alloc] initWithFrame:CGRectMake(235*scale, 10, 77, 36)];
     87     sendButton.backgroundColor = [UIColor lightGrayColor];
     88     [sendButton addTarget:self action:@selector(sendMessage) forControlEvents:UIControlEventTouchUpInside];
     89     // 自动调整与父视图的位置
     90     sendButton.autoresizingMask = UIViewAutoresizingFlexibleTopMargin;
     91     sendButton.layer.cornerRadius = 6.0f;
     92     [sendButton setTitle:@"Send" forState:UIControlStateNormal];
     93     [sendView addSubview:sendButton];
     94 }
     95 // 加载数据
     96 - (void)loadData
     97 {
     98     // 创建两个YXYCChatUser对象
     99     me = [[YXYCChatUser alloc] initWithUsername:@"Peter" avatarImage:[UIImage imageNamed:@"me.png"]];
    100     you = [[YXYCChatUser alloc] initWithUsername:@"You" avatarImage:[UIImage imageNamed:@"noavatar.png"]];
    101     //创建几个YXYCChatData对象
    102     YXYCChatData *first = [YXYCChatData dataWithText:@"Hey,how are you doing? I'm in Paris take a look at this picture." date:[NSDate dateWithTimeIntervalSinceNow:-600] type:ChatTypeMine andUser:me];
    103     YXYCChatData *second = [YXYCChatData dataWithImage:[UIImage imageNamed:@"eiffeltower.jpg"] date:[NSDate dateWithTimeIntervalSinceNow:-290] type:ChatTypeMine andUser:me];
    104     YXYCChatData *third = [YXYCChatData dataWithText:@"Wow..Really cool picture out there. Wish I could be with you" date:[NSDate dateWithTimeIntervalSinceNow:-5] type:ChatTypeSomeone andUser:you];
    105     YXYCChatData *forth = [YXYCChatData dataWithText:@"Maybe next time you can come with me." date:[NSDate dateWithTimeIntervalSinceNow:+0] type:ChatTypeMine andUser:me];
    106     // 通过YXYCChatData对象来初始化Chats(数组)
    107     Chats = [[NSMutableArray alloc] initWithObjects:first,second,third,forth, nil];
    108     // 确认YXYCChatTableViewDataSource的代理
    109     self.chatTable.chatDataSource = self;
    110     // 调用reloadData方法(此方法已被重写)
    111     [self.chatTable reloadData];
    112 }
    113 // 页面消失时移除监听
    114 - (void)viewDidDisappear:(BOOL)animated
    115 {
    116     [self removeNotification];
    117 }
    118 
    119 - (void)sendMessage
    120 {
    121     composing = NO;
    122     YXYCChatData *thisChat = [YXYCChatData dataWithText:msgText.text date:[NSDate date] type:ChatTypeMine andUser:me];
    123     [Chats addObject:thisChat];
    124     [self.chatTable reloadData];
    125     [self showTableView];
    126     // 注销msgText为第一响应者
    127     [msgText resignFirstResponder];
    128     // 清除原来的文本内容
    129     msgText.text = @"";
    130     sendView.frame = CGRectMake(0, appFrame.size.height - 56, 320*scale, 56);
    131     // TODO:注意
    132     NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[Chats count] inSection:0];
    133     // tableView 滚到底部
    134     [self.chatTable scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
    135 }
    136 
    137 #pragma mark -UITextViewDelegat-
    138 //如果用户按回车键,则认为结束编辑,并进行发送消息
    139 - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
    140 {
    141     if ([text isEqualToString:@"
    "]) {
    142         [self sendMessage];
    143         return NO;
    144     }
    145     return YES;
    146 }
    147 
    148 /**
    149  *  @return 返回输入文本在UITextView上的高度
    150  */
    151 - (CGFloat)textY
    152 {
    153     // 设置字体的样式和大小
    154     UIFont *systemFont = [UIFont boldSystemFontOfSize:12];
    155     int width = 225.0, heigth = 10000.0;
    156     NSMutableDictionary *atts = [[NSMutableDictionary alloc] init];
    157     [atts setObject:systemFont forKey:NSFontAttributeName];
    158     // 根据文字量返回CGRect
    159     CGRect size = [msgText.text boundingRectWithSize:CGSizeMake(width, heigth) options:NSStringDrawingUsesLineFragmentOrigin attributes:atts context:nil];
    160     //获取文字的高度
    161     float textHeight = size.size.height;
    162 
    163     float lines = textHeight / lineHeight;
    164     if (lines >= 4) {
    165         lines = 4;
    166     }
    167     if ([msgText.text length] == 0) {
    168         lines = 0.9375f;
    169     }
    170     return 190 - (lines * lineHeight) + lineHeight;
    171 }
    172 // 输入文字时,重新计算和布置sendView的frame,并保持在键盘上方
    173 - (void)textViewDidChange:(UITextView *)textView
    174 {
    175     // 设置文字的样式和大小
    176     UIFont *systemFont = [UIFont boldSystemFontOfSize:12];
    177     int width = 225.0, height = 10000.0;
    178     NSMutableDictionary *atts = [[NSMutableDictionary alloc] init];
    179     [atts setObject:systemFont forKey:NSFontAttributeName];
    180     
    181     CGRect size = [msgText.text boundingRectWithSize:CGSizeMake(width, height) options:NSStringDrawingUsesLineFragmentOrigin attributes:atts context:nil];
    182     float textHeight = size.size.height;
    183     float lines = textHeight / lineHeight;
    184     if (lines > 4) {
    185         lines = 4;
    186     }
    187     
    188     composing = YES;
    189     msgText.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
    190     sendView.frame = CGRectMake(0, appFrame.size.height - keyboardHeight - 56 - (lines * lineHeight) + lineHeight, appFrame.size.width, 56 + (lines * lineHeight) - lineHeight);
    191     
    192     if (prevLines != lines) {
    193         [self shortenTableView];
    194     }
    195     prevLines = lines;
    196 }
    197 
    198 // let's change the frame of the chatTable so we can see the bottom
    199 - (void)shortenTableView
    200 {
    201     [UIView beginAnimations:@"moveView" context:nil];
    202     [UIView setAnimationDuration:0.1];
    203     self.chatTable.frame = CGRectMake(0, 40, appFrame.size.width, appFrame.size.height - keyboardHeight- 56 - 40 );
    204     [UIView commitAnimations];
    205     prevLines = 1;
    206 }
    207 
    208 // show the chatTable as it was
    209 - (void)showTableView
    210 {
    211     [UIView beginAnimations:@"moveView" context:nil];
    212     [UIView setAnimationDuration:0.1];
    213     self.chatTable.frame = CGRectMake(0, 40, appFrame.size.width, appFrame.size.height - 56 - 40);
    214     [UIView commitAnimations];
    215 }
    216 
    217 // when users starts typing change the frame position and shorten the chatTable
    218 - (void)textViewDidBeginEditing:(UITextView *)textView
    219 {
    220     [UIView beginAnimations:@"moveView" context:nil];
    221     [UIView setAnimationDuration:0.3];
    222     sendView.frame = CGRectMake(0, appFrame.size.height - keyboardHeight - 56, appFrame.size.width, 56);
    223     [UIView commitAnimations];
    224     [self shortenTableView];
    225     // 变成第一响应者
    226     [msgText becomeFirstResponder];
    227 }
    228 
    229 - (void)addNotification
    230 {
    231     //键盘出现通知
    232     [[NSNotificationCenter defaultCenter] addObserver:self
    233                                              selector:@selector(handleKeyBoardShow:)
    234                                                  name:UIKeyboardWillShowNotification object:nil];
    235 }
    236 #pragma mark - keyboard delegate
    237 -(void)handleKeyBoardShow:(NSNotification*)notify
    238 {
    239     NSDictionary *info = [notify userInfo];
    240     // 获取键盘的尺寸
    241     CGSize keyboardSize = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
    242     //获取键盘的高度
    243     keyboardHeight = keyboardSize.height;
    244 }
    245 // 移除监听
    246 -(void)removeNotification
    247 {
    248     [[NSNotificationCenter defaultCenter] removeObserver:self];
    249 }
    250 
    251 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
    252 {
    253     return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
    254 }
    255 
    256 
    257 #pragma mark - YXYCChatTableView implementation
    258 // here are the required implementation from your YXYCChatTableViewDataSource
    259 - (NSInteger)rowsForChatTable:(YXYCChatTableView *)tableView
    260 {
    261     return [Chats count];
    262 }
    263 
    264 - (YXYCChatData *)chatTableView:(YXYCChatTableView *)tableView dataForRow:(NSInteger)row
    265 {
    266     return [Chats objectAtIndex:row];
    267 }
    268 
    269 - (void)didReceiveMemoryWarning {
    270     [super didReceiveMemoryWarning];
    271     
    272 }
    273 
    274 
    275 @end
     1 #import <Foundation/Foundation.h>
     2 
     3 @class YXYCChatData;
     4 @class YXYCChatTableView;
     5 @protocol YXYCChatTableViewDataSource <NSObject>
     6 
     7 - (NSInteger)rowsForChatTable:(YXYCChatTableView *)tableView;
     8 - (YXYCChatData *)chatTableView:(YXYCChatTableView *)tableView dataForRow:(NSInteger)row;
     9 
    10 @end
     1 #import <Foundation/Foundation.h>
     2 #import <UIKit/UIKit.h>
     3 @class YXYCChatUser;
     4 //枚举(聊天类型)
     5 typedef enum _YXYCChatType
     6 {
     7     ChatTypeMine = 0,
     8     ChatTypeSomeone = 1
     9 } YXYCChatType;
    10 
    11 @interface YXYCChatData : NSObject
    12 /**
    13  *  聊天的对象类型
    14  */
    15 @property (readonly, nonatomic) YXYCChatType type;
    16 /**
    17  *  日期
    18  */
    19 @property (readonly, nonatomic, strong) NSDate *date;
    20 @property (readonly, nonatomic, strong) UIView *view;
    21 @property (readonly, nonatomic) UIEdgeInsets insets;
    22 /**
    23  *  聊天的用户
    24  */
    25 @property (nonatomic, strong) YXYCChatUser *chatUser;
    26 
    27 // 自定义初始化
    28 + (id)dataWithText:(NSString *)text date:(NSDate *)date type:(YXYCChatType)type andUser:(YXYCChatUser *)_user;
    29 
    30 + (id)dataWithImage:(UIImage *)image date:(NSDate *)date type:(YXYCChatType)type andUser:(YXYCChatUser *)_user;
    31 
    32 + (id)dataWithView:(UIView *)view date:(NSDate *)date type:(YXYCChatType)type andUser:(YXYCChatUser *)_user insets:(UIEdgeInsets)insets;
    33 
    34 @end
      1 #import "YXYCChatData.h"
      2 #import <QuartzCore/QuartzCore.h>
      3 
      4 @implementation YXYCChatData
      5 
      6 //设置一些文本和图片的常量
      7 const UIEdgeInsets textInsetsMine = {5, 10, 11, 17};
      8 const UIEdgeInsets textInsetsSomeone = {5, 15, 11, 10};
      9 const UIEdgeInsets imageInsetsMine = {11, 13, 16, 22};
     10 const UIEdgeInsets imageInsetsSomeone = {11, 18, 16, 14};
     11 
     12 #pragma mark initializers
     13 + (id)dataWithText:(NSString *)text date:(NSDate *)date type:(YXYCChatType)type andUser:(YXYCChatUser *)_user
     14 {
     15     return [[YXYCChatData alloc] initWithText:text date:date type:type andUser:_user];
     16 }
     17 /**
     18  *  初始化
     19  *
     20  *  @param text  内容
     21  *  @param date  日期
     22  *  @param type  聊天对象类型
     23  *  @param _user 用户
     24  *
     25  *  @return YXYCChatData对象
     26  */
     27 - (id)initWithText:(NSString *)text date:(NSDate *)date type:(YXYCChatType)type andUser:(YXYCChatUser *)_user
     28 {
     29     // 设置字体
     30     UIFont *font = [UIFont boldSystemFontOfSize:12];
     31     // 文本显示的宽,以及最大的高度
     32     int width = 225 , height = 10000.0;
     33     NSMutableDictionary *atts = [[NSMutableDictionary alloc] init];
     34     [atts setObject:font forKey:NSFontAttributeName];
     35     // 根据文本内容返回CGRect
     36     CGRect size = [text boundingRectWithSize:CGSizeMake(width, height) options:NSStringDrawingUsesLineFragmentOrigin attributes:atts context:nil];
     37     // 根据返回的尺寸初始化Label
     38     UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, size.size.width, size.size.height)];
     39     // 可多行输入
     40     label.numberOfLines = 0;
     41     // 以单词为单位换行,以单位为单位截断
     42     label.lineBreakMode = NSLineBreakByWordWrapping;
     43     // text参数若存在,Label则显示text的内容;否则Label不显示文本内容
     44     label.text = (text ? text : @"");
     45     label.font = font;
     46     label.backgroundColor = [UIColor clearColor];
     47     UIEdgeInsets insets = (type == ChatTypeMine ? textInsetsMine : textInsetsSomeone);
     48     return [self initWithView:label date:date type:type andUser:_user insets:insets];
     49 }
     50 
     51 + (id)dataWithImage:(UIImage *)image date:(NSDate *)date type:(YXYCChatType)type andUser:(YXYCChatUser *)_user
     52 {
     53     return [[YXYCChatData alloc] initWithImage:image date:date type:type andUser:_user];
     54 }
     55 /**
     56  *  初始化
     57  *
     58  *  @param image 图片
     59  *  @param date  日期
     60  *  @param type  聊天对象的类型
     61  *  @param _user 用户
     62  *
     63  *  @return YXYCChatData对象类型
     64  */
     65 - (id)initWithImage:(UIImage *)image date:(NSDate *)date type:(YXYCChatType)type andUser:(YXYCChatUser *)_user
     66 {
     67     // 获取图片的尺寸
     68     CGSize size = image.size;
     69     // 如果图片的宽大于220,size的宽就等于220,size的高度等于原来的高度与原来的宽度的比例乘以220
     70     if (size.width > 220) {
     71         size.height /= (size.width/220);
     72         size.width = 220;
     73     }
     74     // 根据size的大小初始化imageView
     75     UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, size.width, size.height)];
     76     imageView.image = image;
     77     //设置imageView的圆角半径
     78     imageView.layer.cornerRadius = 5.0;
     79     imageView.layer.masksToBounds = YES;
     80     UIEdgeInsets insets = (type == ChatTypeMine ? imageInsetsMine : imageInsetsSomeone);
     81     return [self initWithView:imageView date:date type:type andUser:_user insets:insets];
     82 }
     83 
     84 + (id)dataWithView:(UIView *)view date:(NSDate *)date type:(YXYCChatType)type andUser:(YXYCChatUser *)_user insets:(UIEdgeInsets)insets
     85 {
     86     return [[YXYCChatData alloc] initWithView:view date:date type:type andUser:(YXYCChatUser *)_user insets:insets];
     87 }
     88 /**
     89  *  初始化
     90  *
     91  *  @param view   view
     92  *  @param date   日期
     93  *  @param type   聊天对象的类型
     94  *  @param _user  用户
     95  *  @param insets
     96  *
     97  *  @return YXYCChatData对象类型
     98  */
     99 - (id)initWithView:(UIView *)view date:(NSDate *)date type:(YXYCChatType)type andUser:(YXYCChatUser *)_user insets:(UIEdgeInsets)insets
    100 {
    101     self = [super init];
    102     if (self) {
    103         _chatUser = _user;
    104         _view = view;
    105         _date = date;
    106         _type = type;
    107         _insets = insets;
    108     }
    109     return self;
    110 }
    111 
    112 @end
     1 #import <UIKit/UIKit.h>
     2 
     3 @interface YXYCChatHeaderTableViewCell : UITableViewCell
     4 /**
     5  *  日期
     6  */
     7 @property (nonatomic, strong) NSDate *date;
     8 + (CGFloat)height;
     9 
    10 @end
     1 #import "YXYCChatHeaderTableViewCell.h"
     2 
     3 @interface  YXYCChatHeaderTableViewCell()
     4 
     5 @property (nonatomic, retain) UILabel *label;
     6 
     7 @end
     8 
     9 @implementation YXYCChatHeaderTableViewCell
    10 
    11 + (CGFloat)height
    12 {
    13     return 30.0;
    14 }
    15 /**
    16  *  设置时间,并把时间显示在YXYCChatHeaderTableViewCell上
    17  */
    18 - (void)setDate:(NSDate *)value
    19 {
    20     // 初始化dateFormatter
    21     NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    22     // 设置日期显示的方式
    23     [dateFormatter setDateStyle:NSDateFormatterMediumStyle];
    24     // 设置时间显示的方式
    25     [dateFormatter setTimeStyle:NSDateFormatterShortStyle];
    26     NSString *text = [dateFormatter stringFromDate:value];
    27     
    28     if (self.label) {
    29         self.label.text = text;
    30         return;
    31     }
    32     self.selectionStyle = UITableViewCellSelectionStyleNone;
    33     // 初始化UILabel
    34     self.label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, [YXYCChatHeaderTableViewCell height])];
    35     //设置Label的文本内容
    36     self.label.text = text;
    37     // 设置Label文本字体的大小
    38     self.label.font = [UIFont boldSystemFontOfSize:12];
    39     // Label文本居中
    40     self.label.textAlignment = NSTextAlignmentCenter;
    41     // 设置Label文字的阴影偏余量
    42     self.label.shadowOffset = CGSizeMake(0, 1);
    43     // 设置Label文字阴影的颜色
    44     self.label.shadowColor = [UIColor whiteColor];
    45     // 设置Label文件的颜色
    46     self.label.textColor = [UIColor darkGrayColor];
    47     // 设置Label的背景颜色
    48     self.label.backgroundColor = [UIColor clearColor];
    49     [self addSubview:self.label];
    50 }
    51 
    52 - (void)awakeFromNib {
    53     // Initialization code
    54 }
    55 
    56 - (void)setSelected:(BOOL)selected animated:(BOOL)animated {
    57     [super setSelected:selected animated:animated];
    58 
    59     // Configure the view for the selected state
    60 }
    61 
    62 @end
     1 #import <Foundation/Foundation.h>
     2 #import <UIKit/UIKit.h>
     3 @interface YXYCChatUser : NSObject
     4 /**
     5  *  用户名字
     6  */
     7 @property (nonatomic, strong) NSString *username;
     8 /**
     9  *  头像
    10  */
    11 @property (nonatomic, strong) UIImage *avatar;
    12 /**
    13  *  初始化
    14  *
    15  *  @param user  用户
    16  *  @param image 头像
    17  *
    18  *  @return 返回id类型
    19  */
    20 - (id)initWithUsername:(NSString *)user avatarImage:(UIImage *)image;
    21 
    22 @end
     1 #import "YXYCChatUser.h"
     2 
     3 @implementation YXYCChatUser
     4 
     5 @synthesize avatar;
     6 @synthesize username;
     7 
     8 - (id)initWithUsername:(NSString *)user avatarImage:(UIImage *)image
     9 {
    10     self = [super init];
    11     if (self) {
    12         self.avatar = [image copy];
    13         self.username = [user copy];
    14     }
    15     return self;
    16 }
    17 
    18 @end
     1 #import <UIKit/UIKit.h>
     2 #import "YXYCChatData.h"
     3 
     4 @interface YXYCChatTableViewCell : UITableViewCell
     5 /**
     6  *  日期
     7  */
     8 @property (nonatomic, strong) YXYCChatData *data;
     9 /**
    10  *  设置日期
    11  */
    12 - (void)setData:(YXYCChatData *)data;
    13 
    14 @end
      1 #import "YXYCChatTableViewCell.h"
      2 #import "YXYCChatData.h"
      3 #import <QuartzCore/QuartzCore.h>
      4 #import "YXYCChatUser.h"
      5 
      6 @interface YXYCChatTableViewCell ()
      7 
      8 @property (nonatomic, retain) UIView *customView;
      9 @property (nonatomic, retain) UIImageView *bubbleImage;
     10 /**
     11  *  头像
     12  */
     13 @property (nonatomic, retain) UIImageView *avatarImage;
     14 
     15 //- (void)setupInternalData;
     16 
     17 @end
     18 
     19 @implementation YXYCChatTableViewCell
     20 
     21 @synthesize data = _data;
     22 
     23 - (void)setData:(YXYCChatData *)data
     24 {
     25     _data = data;
     26     [self rebuildUserInterface];
     27 }
     28 
     29 - (void)rebuildUserInterface
     30 {
     31     self.selectionStyle = UITableViewCellSelectionStyleNone;
     32     // 如果bubbleImage为空,则创建
     33     if (!self.bubbleImage) {
     34         self.bubbleImage = [[UIImageView alloc] init];
     35         [self addSubview:self.bubbleImage];
     36     }
     37     YXYCChatType type = self.data.type;
     38     CGFloat width = self.data.view.frame.size.width;
     39     CGFloat height = self.data.view.frame.size.height;
     40     CGFloat x = (type == ChatTypeSomeone) ? 0 : self.frame.size.width - width - self.data.insets.left - self.data.insets.right;
     41     CGFloat y = 0;
     42     // 如果用户有头像,则显示头像
     43     if (self.data.chatUser) {
     44         YXYCChatUser *thisUser = self.data.chatUser;
     45         [self.avatarImage removeFromSuperview];
     46         self.avatarImage = [[UIImageView alloc] initWithImage:(thisUser.avatar ? thisUser.avatar : [UIImage imageNamed:@"noavatar.png"])];
     47         self.avatarImage.layer.cornerRadius = 9.0;
     48         self.avatarImage.layer.masksToBounds = YES;
     49         // 设置avatarImage的边框颜色
     50         self.avatarImage.layer.borderColor = [UIColor colorWithWhite:0.0 alpha:0.2].CGColor;
     51         // 设置avatarImage边框的粗细
     52         self.avatarImage.layer.borderWidth = 1.0;
     53         // 计算x的位置
     54         CGFloat avatarX = (type == ChatTypeSomeone) ? 2 : self.frame.size.width - 52;
     55         CGFloat avatarY = self.frame.size.height - 50;
     56         //设计frame
     57         self.avatarImage.frame = CGRectMake(avatarX, avatarY, 50, 50);
     58         [self addSubview:self.avatarImage];
     59         CGFloat delta = self.frame.size.height - (self.data.insets.top + self.data.insets.bottom + self.data.view.frame.size.height);
     60         if (delta > 0) y = delta;
     61         if (type == ChatTypeSomeone) x += 54;
     62         if (type == ChatTypeMine) x -= 54;
     63     }
     64     [self.customView removeFromSuperview];
     65     self.customView = self.data.view;
     66     self.customView.frame = CGRectMake(x + self.data.insets.left, y + self.data.insets.top, width, height);
     67     [self.contentView addSubview:self.customView];
     68     //
     69     if (type == ChatTypeSomeone) {
     70         //创建一个内容可拉伸,而边角不拉伸的图片,需要两个参数,第一个是左边不拉伸区域的宽度,第二个参数是上面不拉伸的高度。
     71         self.bubbleImage.image = [[UIImage imageNamed:@"yoububble.png"] stretchableImageWithLeftCapWidth:21 topCapHeight:14];
     72     }else{
     73         self.bubbleImage.image = [[UIImage imageNamed:@"mebubble.png"] stretchableImageWithLeftCapWidth:15 topCapHeight:14];
     74     }
     75     self.bubbleImage.frame = CGRectMake(x, y, width + self.data.insets.left + self.data.insets.right, height + self.data.insets.top + self.data.insets.bottom);
     76 }
     77 
     78 //- (void)setUP:(YXYCChatData *)value
     79 //{
     80 //    self.data = value;
     81 //    [self rebuildUserInterface];
     82 //}
     83 
     84 - (void)setFrame:(CGRect)frame
     85 {
     86     [super setFrame:frame];
     87     [self rebuildUserInterface];
     88 }
     89 
     90 - (void)awakeFromNib {
     91     // Initialization code
     92 }
     93 
     94 - (void)setSelected:(BOOL)selected animated:(BOOL)animated {
     95     [super setSelected:selected animated:animated];
     96 
     97     // Configure the view for the selected state
     98 }
     99 
    100 @end
     1 #import <UIKit/UIKit.h>
     2 #import "YXYCChatTableViewDataSource.h"
     3 #import "YXYCChatTableViewCell.h"
     4 
     5 typedef enum _ChatBubbleTypingType
     6 {
     7     ChatBubbleTypingTypeNobody = 0,
     8     ChatBubbleTypingTypeMe = 1,
     9     ChatBubbleTypingTypeSomebody = 2
    10 } ChatBubbleTypingType;
    11 
    12 @interface YXYCChatTableView : UITableView
    13 /**
    14  *  添加代理
    15  */
    16 @property (nonatomic, assign) id<YXYCChatTableViewDataSource> chatDataSource;
    17 /**
    18  *  时间间隔
    19  */
    20 @property (nonatomic) NSTimeInterval snapInterval;
    21 @property (nonatomic) ChatBubbleTypingType typingBubble;
    22 
    23 @end
      1 #import "YXYCChatTableView.h"
      2 #import "YXYCChatData.h"
      3 #import "YXYCChatHeaderTableViewCell.h"
      4 
      5 @interface YXYCChatTableView ()<UITableViewDelegate,UITableViewDataSource>
      6 
      7 @property (nonatomic, strong) NSMutableArray *bubbleSection;
      8 
      9 @end
     10 
     11 @implementation YXYCChatTableView
     12 
     13 - (id)init
     14 {
     15     self = [super init];
     16     if (self) [self initializer];
     17     return self;
     18 }
     19 
     20 - (void)initializer
     21 {
     22     self.backgroundColor = [UIColor clearColor];
     23     // 隐藏cell与cell之间的分离线
     24     self.separatorStyle = UITableViewCellSeparatorStyleNone;
     25     // 设置代理
     26     self.delegate = self;
     27     self.dataSource = self;
     28     self.snapInterval = 60 * 60 * 24;//一天的时间
     29     self.typingBubble = ChatBubbleTypingTypeNobody;
     30 }
     31 
     32 - (id)initWithFrame:(CGRect)frame
     33 {
     34     self = [super initWithFrame:frame];
     35     if (self) [self initializer];
     36     return self;
     37 }
     38 
     39 - (id)initWithFrame:(CGRect)frame style:(UITableViewStyle)style
     40 {
     41     self = [super initWithFrame:frame style:UITableViewStylePlain];
     42     if (self) {
     43         [self initializer];
     44     }
     45     return self;
     46 }
     47 
     48 #pragma mark - 重写tableView的部分方法-
     49 - (void)reloadData
     50 {
     51     self.showsHorizontalScrollIndicator = NO;
     52     self.showsVerticalScrollIndicator = NO;
     53     self.bubbleSection = nil;
     54     int count = 0;
     55     self.bubbleSection = [[NSMutableArray alloc] init];
     56     if (self.chatDataSource && (count = (int)[self.chatDataSource rowsForChatTable:self]) > 0) {
     57         NSMutableArray *bubbleData = [[NSMutableArray alloc] initWithCapacity:count];
     58         for (int i = 0; i < count; i++) {
     59             NSObject *object = [self.chatDataSource chatTableView:self dataForRow:i];
     60             assert([object isKindOfClass:[YXYCChatData class]]);
     61             [bubbleData addObject:object];
     62         }
     63         // 根据时间进行排列
     64         [bubbleData sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
     65             YXYCChatData *bubbleData1 = (YXYCChatData *)obj1;
     66             YXYCChatData *bubbleData2 = (YXYCChatData *)obj2;
     67             return [bubbleData1.date compare:bubbleData2.date];
     68         }];
     69         // 以GMT时间的偏移秒数来初始化
     70         NSDate *last = [NSDate dateWithTimeIntervalSince1970:0];
     71         NSMutableArray *currentSection = nil;
     72         for (int i = 0; i < count; i++) {
     73             YXYCChatData *data = (YXYCChatData *)[bubbleData objectAtIndex:i];
     74             // 如果时间大于一天的时间就存入self.bubbleSection(用于分区)
     75             if ([data.date timeIntervalSinceDate:last] > self.snapInterval) {
     76                 currentSection = [[NSMutableArray alloc] init];
     77                 [self.bubbleSection addObject:currentSection];
     78             }
     79             [currentSection addObject:data];
     80             last = data.date;
     81         }
     82     }
     83     [super reloadData];
     84 }
     85 
     86 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
     87 {
     88     int result = (int)[self.bubbleSection count];
     89     if (self.typingBubble != ChatBubbleTypingTypeNobody) {
     90         result ++;
     91     }
     92     return result;
     93 }
     94 
     95 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
     96 {
     97     if (section >= [self.bubbleSection count]) {
     98         return 1;
     99     }
    100     return [[self.bubbleSection objectAtIndex:section] count] + 1;
    101 }
    102 
    103 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    104 {
    105     // Header
    106     if (indexPath.row == 0) {
    107         return [YXYCChatHeaderTableViewCell height];
    108     }
    109     YXYCChatData *data = [[self.bubbleSection objectAtIndex:indexPath.section] objectAtIndex:indexPath.row - 1];
    110     return MAX(data.insets.top + data.view.frame.size.height + data.insets.bottom, 52);
    111 }
    112 
    113 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    114 {
    115     //Header based on snapInterval
    116     if (indexPath.row == 0) {
    117         static NSString *cellId = @"HeaderCell";
    118         YXYCChatHeaderTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId];
    119         YXYCChatData *data = [[self.bubbleSection objectAtIndex:indexPath.section] objectAtIndex:0];
    120         if (cell == nil) {
    121             cell = [[YXYCChatHeaderTableViewCell alloc] init];
    122         }
    123         cell.date = data.date;
    124         return cell;
    125     }
    126     //Standard
    127     static NSString * cellId = @"ChatCell";
    128     YXYCChatTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId];
    129     YXYCChatData *data = [[self.bubbleSection objectAtIndex:indexPath.section] objectAtIndex:indexPath.row - 1];
    130     if (cell == nil) {
    131         cell = [[YXYCChatTableViewCell alloc] init];
    132     }
    133     cell.data = data;
    134     return cell;
    135 }
    136 
    137 @end
  • 相关阅读:
    J2EE(一)——开发简单WEB服务器
    日报--2015年7月10日
    MVC @Html控件(转载)
    Asp.NET MVC--【Asp.net】
    附加到进程 调试技巧--【VS】
    快速阅读学习方法笔记
    匿名函数和闭包--【JavaScript】
    Repeater显示数据--[Asp.Net]
    FileUpLoad上传文件--[Asp.Net]
    35Canlender--[Asp.Net]
  • 原文地址:https://www.cnblogs.com/lantu1989/p/4745648.html
Copyright © 2020-2023  润新知