在iOS中创建消息传递屏幕

时间:2014-07-27 09:02:01

标签: ios objective-c uitableview messaging

我目前正在开发一款以消息传递为核心功能的iOS应用。消息传递屏幕可能变得非常复杂,特别是试图使它们达到今天的标准。我想知道开发人员用来创建消息传递屏幕的解决方案。有没有一个好的库开始(我已经检查了JSQMessagesViewController和几乎所有其他CocoaPod的消息)或者我应该从头开始?

我想要的消息传递屏幕并不是太复杂,我应该能够通过表视图,几个自定义单元格和一些约束来完成它。我正在努力确定是否应该浪费时间定制一些东西,而我自己可以自己制作。

我该怎么做,自定义一个现有的库,或者只是从头开始做?

任何提示?

1 个答案:

答案 0 :(得分:2)

我意识到这个问题已经存在了一段时间,但由于它没有接受的答案,我将提交我的解决方案。我在下面显示的部分用于显示消息,不包括回复小部件。这应该有助于让人们开始朝着我想要的方向前进。

我使用tableview,包含UITextView属性的自定义单元格(但未在storyboard中添加textview,在代码中实例化)以及包含我的SDMessage类实例的表数据数组来完成此操作。

以下是SDMessage类接口文件的内容:

@interface SDMessage : NSObject

@property (nonatomic, strong) NSNumber *message_id;
@property (nonatomic, strong) NSString *message_sender;
@property (nonatomic, strong) NSString *message_content;
@property (nonatomic, strong) NSString *their_id;
@property (nonatomic, strong) NSString *timestamp;
@property (nonatomic, strong) NSDate *dateTime;
@property (nonatomic, strong) NSString *prettyTimestamp;
@property (nonatomic, strong) NSNumber *seen;


@end

我的tableview委托方法如下:

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [self.tableData count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"MsgDetailCell";
    MsgDetailCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];


    if (!cell) {
        cell = [[MsgDetailCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
        cell.frame = CGRectMake(2, 2, tableView.frame.size.width - 4, 30);
    }

    // Since we are creating a new UITextfield with every load, set any existing UITextfield instance to nil
    [cell.message removeFromSuperview];
    cell.message = nil;


    // get the data for this cell (returns self.tableData[indexPath.row])
    SDMessage *cellData = [self cellDataForRowAtIndexPath:indexPath];

    // get sender id to configure appearance (if we're sending a message it will appear 
    // on the right side, if we received a message the message will be on the left side of the screen)
    long long   theirId = [cellData.message_sender longLongValue];

    // we have to do this in code so we can set the frame once and avoid cut off text
    cell.message = [[UITextView alloc] init];

    // set cell text
    cell.message.text = cellData.message_content;

    // set font and text size (I'm using custom colors here defined in a category)
    [cell.message setFont:[UIFont fontWithName:kMessageFont size:kMessageFontSize]];
    [cell.message setTextColor:[UIColor gh_messageTextColor]];

    // our messages will be a different color than their messages
    UIColor *msgColor = (theirId == _myUid) ? [UIColor gh_myMessageBgColor] : [UIColor gh_theirMessageBgColor];

    // I want the cell background to be invisible, and only have the 
    // message background be colored
    cell.backgroundColor = [UIColor clearColor];
    cell.message.backgroundColor = msgColor;
    cell.message.layer.cornerRadius = 10.0;

    // make the textview fit the content (kMessageWidth = 220, kMessageBuffer = 15 ... buffer is amount of space from edge of cell)
    CGSize newSize = [cell.message sizeThatFits:CGSizeMake(kMessageWidth, MAXFLOAT)];
    CGRect newFrame;

    // since we are placing the message bubbles justified right or left on the screen
    // we determine if this is our message or someone else's message and set the cell
    // origin accordingly... (if the sender of this message (e.g. theirId) is us, then take the width
    // of the cell, subtract our message width and our buffer and set that x position as our origin.
    // this will position messages we send on the right side of the cell, otherwise the other party
    // in our conversation sent the message, so our x position will just be whatever the buffer is. (in this case 15)
    float originX = (theirId == _myUid) ? cell.frame.size.width - kMessageWidth - kMessageBuffer : kMessageBuffer;

    // set our origin at our calculated x-point, and y position of 10
    newFrame.origin = CGPointMake(originX, 10);

    // set our message width and newly calculated height
    newFrame.size = CGSizeMake(fmaxf(newSize.width, kMessageWidth), newSize.height);

    // set the frame of our textview and disable scrolling of the textview
    cell.message.frame = newFrame;
    cell.message.scrollEnabled  = NO;
    cell.userInteractionEnabled = NO;

    // add our textview to our cell
    [cell addSubview:cell.message];

    return cell;
}



-(CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // we need to make sure our cell is tall enough so we don't cut off our message bubble
    MsgDetailCell *cell = (MsgDetailCell*)[self tableView:self.tableview cellForRowAtIndexPath:indexPath];

    // get the size of the message for this cell
    CGSize newSize = [cell.message sizeThatFits:CGSizeMake(kMessageWidth, MAXFLOAT)];

    // get the height of the bubble and add a little buffer of 20
    CGFloat textHeight  = newSize.height + 20;

    // don't make our cell any smaller than 60
    textHeight          = (textHeight < 60) ? 60 : textHeight;

    return textHeight;
}


-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    SLog(@"didSelectRow: %ld", (long)indexPath.row);
}


- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
    return NO;
}

- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
    return NO;
}

-(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
    return 0.01;
}

-(UIView*)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
    return [UIView new];
}

这给了我一个消息屏幕tableview,如下所示: Messaging Screen Image