ios 气泡聊天

最近做的项目里面,有几个模块用到了聊天功能和评论回复的功能,使用的频率还是很高的,所以抽时间做了这个博客,希望能给自己和别人带来方便,

具体代码如下:

1,创建model,

#import <Foundation/Foundation.h>

@interface MessageObj : NSObject

@property(nonatomic,copy)NSString *message;
@property(nonatomic,assign)BOOL isMe;

@end

2,自定义cell

1)声明一个label和imageview

@property(nonatomic,strong)UIImageView *messageImg;
@property(nonatomic,strong)UILabel *messageLab;

2)初始化构造方法

-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        //这里只需要初始化,不需要设置具体的坐标
        self.backgroundColor = [UIColor clearColor];
        self.selectionStyle = UITableViewCellSelectionStyleNone;
        _messageImg = [[UIImageView alloc]init];
        [self addSubview:_messageImg];
        _messageLab = [[UILabel alloc]init];
        _messageLab.numberOfLines = 0;
        [self addSubview:_messageLab];
    }
    
    return self;
}

3,准备工作已做好,现在进行聊天功能的完善

1)声明所需的成员变量

@interface ViewController ()<UITextFieldDelegate,UITableViewDelegate,UITableViewDataSource>
{
    UITextField *tf;
    UIView *inputView;
    UIButton *rightBtn;
    UITableView *tableViews;
    
    int _count;
    NSMutableArray *_datasArray;
}

2)界面的布局,做好适配

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    _datasArray = [NSMutableArray array];//这里一定要记得初始化
    
    self.title = @"气泡聊天";
    self.view.backgroundColor = [UIColor whiteColor];
    
    tableViews = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, MainScreen_width, self.view.bounds.size.height-60) style:UITableViewStylePlain];
    tableViews.delegate = self;
    tableViews.dataSource = self;
    tableViews.tableFooterView = [[UIView alloc]init];
    tableViews.separatorStyle = UITableViewCellSeparatorStyleNone;
    [self.view addSubview:tableViews];
    
    
    inputView = [[UIView alloc]initWithFrame:CGRectMake(0, MainScreen_height - 50, MainScreen_width, 60)];
    inputView.backgroundColor = RGBAColor(159, 159, 159, 1);
    [self.view addSubview:inputView];
    
    tf = [[UITextField alloc]initWithFrame:CGRectMake(10, 3, MainScreen_width - 60, 50)];
    tf.delegate = self;
    tf.returnKeyType = UIReturnKeyDefault;
    [inputView addSubview:tf];
    
    rightBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    rightBtn.frame = CGRectMake(MainScreen_width - 50-5, 3, MainScreen_width - tf.frame.size.width, 50);
    [rightBtn setTitle:@"发送" forState:UIControlStateNormal];
    [rightBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    [rightBtn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];
    [inputView addSubview:rightBtn];
    
    //增加监听,当键盘改变是发出消息
    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
    
    //增加监听,当键盘退出时发出消息
    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}

注:这里最后,声明了两个通知,这样是为了,监听键盘弹出和弹下的高度,

具体实现如下:

-(void)keyboardWillShow:(NSNotification *)hNotification
{
    //获取键盘的高度
    NSDictionary *userInfo = [hNotification userInfo];
    NSValue *aValue = [userInfo objectForKey:UIKeyboardFrameEndUserInfoKey];
    CGRect keyboardRect = [aValue CGRectValue];
    int height = keyboardRect.size.height;//获取到的键盘的高度
    [UIView animateWithDuration:0.1 animations:^{
        CGRect tableFrame = tableViews.frame;
        tableFrame.size.height = MainScreen_height - height - 60;
        tableViews.frame = tableFrame;
        CGRect rect = inputView.frame;
        rect.origin.y = MainScreen_height - height - 60;
        inputView.frame = rect;
    }];
    
}

-(void)keyboardWillHide:(NSNotification *)hNotification
{
    [UIView animateWithDuration:0.1 animations:^{
        CGRect tableViewRect = tableViews.frame;
        tableViewRect.size.height = MainScreen_height- 60;
        tableViews.frame = tableViewRect;
        CGRect rect = inputView.frame;
        rect.origin.y = MainScreen_height - 60;
        inputView.frame = rect;
    }];
    
    if (_datasArray.count > 0)
    {
        //让表的最后一行滚动到表的底部
        NSIndexPath * indexPath = [NSIndexPath indexPathForRow:_datasArray.count-1 inSection:0];
        [tableViews scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
    }
}

3)发送按钮的点击方法

-(void)btnClick:(id)sender
{
    _count ++;//这里声明一个int类型的变量是为了下面区分是否是自己
    
    //这里使用model,会很方便,单独作为对象来使用,方便进行设置
    MessageObj *objets = [[MessageObj alloc]init];
    objets.message = tf.text;
    
    if (objets.message != nil && [objets.message isEqualToString:@""]) {
        UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"温馨体香" message:@"不能为空" delegate:nil cancelButtonTitle:@"取消" otherButtonTitles:nil, nil];
        [alertView show];
        return;
    }else
    {
        //这里通过第一个发送的顺序,设为自己,其他为别人,然后绑定一个bool值的状态,yes为自己,no为别人
        if (_count%2 == 1) {
            objets.isMe = YES;
        }else
        {
            objets.isMe = NO;
        }
        
        [_datasArray addObject:objets];
        NSLog(@"--%lu",(unsigned long)_datasArray.count);
        [tableViews reloadData];
        
        //让表的最后一行滚动到表的底部
        NSIndexPath * indexPath = [NSIndexPath indexPathForRow:_datasArray.count-1 inSection:0];
        [tableViews scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
        
        tf.text = nil;
    }
}

注:这里面有比较重要的地方,代码很详细,我就不一一解释了,大家可以自己看

4)表的具体展现和自适应

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return _datasArray.count;
}

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    MessageObj *object = _datasArray[indexPath.row];
    
    CGFloat contentW = MainScreen_width - 34;
    
    UIFont *fnt = [UIFont fontWithName:@"HelveticaNeue" size:18.0f];
    
    //ios 7 以后的方法,这里得到自适应的高度,从而动态的设置cell的高度
    CGRect tempRect = [object.message boundingRectWithSize:CGSizeMake(contentW, 1000) options:NSStringDrawingUsesLineFragmentOrigin attributes:[NSDictionary dictionaryWithObjectsAndKeys:fnt,NSFontAttributeName, nil] context:nil];
    CGFloat contenH = tempRect.size.height;
    
    return contenH + 20;
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellIdentifiers = @"CELLES";
    EightyTableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
    if (!cell) {
        
        cell = [[EightyTableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifiers];
        cell.selectionStyle = UITableViewCellSelectionStyleDefault;
    }
    
    MessageObj *object = _datasArray[indexPath.row];
    /*
     CGFloat contentW = MainScreen_width - 34;
     
     UIFont *fnt = [UIFont fontWithName:@"HelveticaNeue" size:18.0f];
     
     CGRect tempRect = [object.message boundingRectWithSize:CGSizeMake(320, 1000) options:NSStringDrawingUsesLineFragmentOrigin attributes:[NSDictionary dictionaryWithObjectsAndKeys:fnt,NSFontAttributeName, nil] context:nil];
     CGFloat contenH = tempRect.size.height;
     */
    
    //在这里进行宽度和高度的自适应
    UIFont *fnt = [UIFont fontWithName:@"HelveticaNeue" size:18.0f];
    CGSize size = CGSizeMake(MainScreen_width,1000);
    CGSize labSize = [object.message sizeWithFont:fnt constrainedToSize:size lineBreakMode:UILineBreakModeWordWrap];
    
    
    if (object.isMe == YES) {
        
        cell.messageLab.frame = CGRectMake(20, 0, labSize.width, labSize.height);
        cell.messageLab.textAlignment = NSTextAlignmentLeft;
        cell.messageLab.numberOfLines = 0;
        cell.messageImg.frame = CGRectMake(10, 0, labSize.width+20, labSize.height+10);
    }else
    {
        cell.messageLab.frame = CGRectMake(MainScreen_width - 20 - labSize.width, 5, labSize.width, labSize.height);
        cell.messageLab.numberOfLines = 0;
        cell.messageLab.textAlignment = NSTextAlignmentRight;
        cell.messageImg.frame = CGRectMake(MainScreen_width - 30 - labSize.width, 2, labSize.width + 20, labSize.height + 10);
    }
    
    NSString *imageName = object.isMe?@"bubbleSelf.png":@"bubble.png";
    UIImage *oldImage = [UIImage imageNamed:imageName];
    UIImage *newImage = [oldImage stretchableImageWithLeftCapWidth:18 topCapHeight:8];
    cell.messageImg.image = newImage;
    cell.messageLab.font = fnt;
    cell.messageLab.text = object.message;
    
    return  cell;
    
}

注:主要就是cellforrow方法里面的lab自适应坐标的设置,还有气泡背景图片的坐标设置,还有heightforrow里面根据lab的高度,动态判定cell的高度

效果图如下:

如需源码,可从这里下载:http://code.cocoachina.com/view/131767

原文地址:https://www.cnblogs.com/hero11223/p/5627049.html