聊天气泡sms

来源:互联网 发布:gif调色软件 编辑:程序博客网 时间:2024/04/29 03:35

iPhone户对内置的短信应用程序并不陌生以,它用一个超可爱的气泡方式显示短信,如图1。

图1

 

但是,这种创新的UI功能并没有开放给iPhone开发者,因此如果你想开发一款类似的app,你必须自己实现它。我命名这种UI叫着BubbleUI,它以聊天的方式显示信息。一个很好的例子就是你开发一款聊天app,两人聊天的内容用气泡显示。

 

本文我将向大家介绍开发类似sms应用程序的详细步骤。

 

 

准备气泡图片

首先,你需要像气泡的图片。我用是图2这张图片。

图2

 

如果细心的朋友可能发现内置的短信应用它的气泡大小不是固定的,它根据字的多少而变化。因此,我们的消息气泡应能相应的扩展与收缩。在不影响气泡外貌的情况下最简单的方法就是将它分成9个小图片,像图3那样。

图3

 

 

如果你想扩展气泡的高度,只需要在垂直方向上将中间一排的图片简单的延伸(如图4的左图)。如果你想扩展气泡的宽度,只需要在水平方向上将中间一列的图片简单的延伸(如图4右图)。

图4

 

要显示的消息就覆盖在气泡上面就行了。

 

在此提醒大家,如果你想减少工作量,你可以不用将图片分成9张小图片,而只需要将整张气泡延伸。但这也要看你用的气泡图片样式,如果只一张矩图图片,那么延伸整张图片是最简单的方法。

 

 

创建工程

 

现在你知道生成消息气泡的方法,那进一步是创建代码工程。开启xcode并新建一个View-based(iphone)工程,并名命为BubbleUI。在Resources目录新建一个名叫icons的组。并把上面说到的9张小图拖到Icons分组中,如图5。

图5

 

双击BubbleUIViewController.xib激活interfaceBuilder(xcode3xcode与IB是分开的,xcode4中内置了IB).在View中添加一个TextFild,一个Round Rect Button,一个Table View,如6。

图6

 

选择了Table View去展消息气泡。是因它可以滚,用可以容易地看到所有消息,并且一个消息气泡就是一个cell。这样你就可以在TableView自定义每个消息占用空

 

中Table View的属性看器,并设置如图7所示。

图7

 

设置背景色为亮蓝(RGB值为219,226,237),这个色与我所使用的气片图片更搭配。Separator属性设为none是为了隐藏TableView每排的分隔线,这样一来就不像是TableView了。

 

下一步,设置View的背景色,使其与Table View更协调,如图8

图8

 

修改BubbleUIViewController.h的代码如下:

viewplaincopyto clipboardprint?
  1. #import <UIKit/UIKit.h>  
  2.    
  3. @interface BubbleUIViewController UIViewController  
  4.     //---add this---  
  5.     IBOutlet UITextField *itemName;  
  6.     IBOutlet UITableView *tableView;  
  7.     //--------------  
  8.  
  9.    
  10. //---add this---  
  11. @property (nonatomic, retain) UITextField *itemName;  
  12. @property (nonatomic, retain) UITableView *tableView;  
  13.    
  14. -(IBAction) doneEditing:(id) sender;  
  15. -(IBAction) btnAdd:(id) sender;  
  16. //--------------  
  17.    
  18. @end  
 

 

回到IB, 设置Table View的数据源与代理为File's Owner item.并前联变量tableView 到Table View, 如图9.

图9

 

下一步,连接Text Field view的事件Did End OnExit到响应方法doneEditing:上,出口到itemName,10.

图10

 

最后,连接圆形button的事件Touch UpInside到响方法btnAdd:,如11

图11

 

BubbleUIViewController.m中,添加如下代

首先,声明一些变量与常量:

viewplaincopyto clipboardprint?
  1. #import "BubbleUIViewController.h"  
  2.    
  3. @implementation BubbleUIViewController  
  4.    
  5. //---add this---  
  6. @synthesize itemName;  
  7. @synthesize tableView;  
  8.    
  9. NSMutableArray *listOfMessages;  
  10. NSMutableArray *dateOfMessages;  
  11.    
  12. static CGFloat const FONTSIZE 14.0;  
  13. static int const DATELABEL_TAG 1;  
  14. static int const MESSAGELABEL_TAG 2;  
  15. static int const IMAGEVIEW_TAG_1 3;  
  16. static int const IMAGEVIEW_TAG_2 4;  
  17. static int const IMAGEVIEW_TAG_3 5;  
  18. static int const IMAGEVIEW_TAG_4 6;  
  19. static int const IMAGEVIEW_TAG_5 7;  
  20. static int const IMAGEVIEW_TAG_6 8;  
  21. static int const IMAGEVIEW_TAG_7 9;  
  22. static int const IMAGEVIEW_TAG_8 10;  
  23. static int const IMAGEVIEW_TAG_9 11;  
  24.    
  25. int bubbleFragment_width, bubbleFragment_height;  
  26. int bubble_x, bubble_y;  
  27. //--------------  
 

 

方法doneEditing:实现如下:

 

viewplaincopyto clipboardprint?
  1. -(IBAction) doneEditing9id) sender  
  2.     [sender resignFirstResponder];  
  3.  
 

 

viewDidLoad初始化各种变量与数组:

 

viewplaincopyto clipboardprint?
  1. (void)viewDidLoad  
  2.    
  3.     //---add this---  
  4.     //---location to display the bubble fragment---   
  5.     bubble_x 10;  
  6.     bubble_y 20;  
  7.    
  8.     //---size of the bubble fragment---  
  9.     bubbleFragment_width 56;  
  10.     bubbleFragment_height 32;  
  11.    
  12.     //---contains the messages---  
  13.     listOfMessages [[NSMutableArray alloc] init];  
  14.    
  15.     //---contains the date for each message---  
  16.     dateOfMessages [[NSMutableArray alloc] init];      
  17.    
  18.     //---add message---  
  19.     [listOfMessages addObject:@"Hello there!"];  
  20.     [dateOfMessages addObject:[NSString stringWithFormat:@"%@",[NSDate date]]];  
  21.     //--------------  
  22.    
  23.     [super viewDidLoad];  
  24.  
 

 

设置Table View的sections数量为1:

 

viewplaincopyto clipboardprint?
  1. (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView  
  2.     return 1;  
  3.  

 

listOfMessages包括了所有要显示的消息,因此Table View的排数就是数的元个数:

viewplaincopyto clipboardprint?
  1. (NSInteger)tableView:(UITableView *)tableView     
  2.  numberOfRowsInSection:(NSInteger)section  
  3.     return [listOfMessages count];  
  4.  
 

 

 

简单,所有的消息气泡都用固定的度,差不多是片的3倍大小。所有要显示的消息也受限于该长度。左右各25像边缘。因此,只需要计算要显示字符串的需要高度。用下面代码就可以解决问题:

 

viewplaincopyto clipboardprint?
  1. //---calculate the height for the message---  
  2. -(CGFloat) labelHeight:(NSString *) text  
  3.     CGSize maximumLabelSize CGSizeMake((bubbleFragment_width 3) 25,9999);  
  4.     CGSize expectedLabelSize [text sizeWithFont:[UIFont systemFontOfSize: FONTSIZE]   
  5.                                 constrainedToSize:maximumLabelSize   
  6.                                     lineBreakMode:UILineBreakModeWordWrap];   
  7.     return expectedLabelSize.height;  
  8.  
 

 

上面这个方法输入参数为一个字符串,然后根据规定长度计算所占空间的高度。由于TableView每一排显示一个消息气泡,每一个消息气泡高度不一样,那就要设置每一排的高度。能过下面代码可以办到:

viewplaincopyto clipboardprint?
  1. //---returns the height for the table view row---  
  2. (CGFloat)tableView:(UITableView *)tableView   
  3. heightForRowAtIndexPath:(NSIndexPath *)indexPath    
  4.    
  5.     int labelHeight [self labelHeight:[listOfMessages  
  6.                           objectAtIndex:indexPath.row]];  
  7.     labelHeight -= bubbleFragment_height;  
  8.     if (labelHeight<0) labelHeight 0;  
  9.    
  10.     return (bubble_y bubbleFragment_height labelHeight) 5;      
  11.  
 

 

最有挑占的部份就是把要显示的气泡消息交给TableView显示出来。让我们先来总览代码,我等一下再介绍之。这是该方法全部代码:

viewplaincopyto clipboardprint?
  1. (UITableViewCell *)tableView:(UITableView *)tableView   
  2.          cellForRowAtIndexPath:(NSIndexPath *)indexPath  
  3.    
  4.     static NSString *CellIdentifier @"Cell" 
  5.    
  6.     //---add this---  
  7.     UILabel* dateLabel nil;  
  8.     UILabel* messageLabel nil;  
  9.     UIImageView *imageView_top_left nil;  
  10.     UIImageView *imageView_top_middle nil;  
  11.     UIImageView *imageView_top_right nil;  
  12.    
  13.     UIImageView *imageView_middle_left nil;  
  14.     UIImageView *imageView_middle_right nil;  
  15.     UIImageView *imageView_middle_middle nil;  
  16.    
  17.     UIImageView *imageView_bottom_left nil;  
  18.     UIImageView *imageView_bottom_middle nil;  
  19.     UIImageView *imageView_bottom_right nil;  
  20.     //--------------  
  21.    
  22.     UITableViewCell *cell [tableView   
  23.         dequeueReusableCellWithIdentifier:CellIdentifier];  
  24.    
  25.     if (cell == nil)  
  26.         cell [[[UITableViewCell alloc] initWithFrame:CGRectZero  
  27.                                        reuseIdentifier:CellIdentifier]   
  28.                                        autorelease];  
  29.    
  30.         //---add this---  
  31.         //---date---  
  32.         dateLabel [[[UILabel alloc] init] autorelease];  
  33.         dateLabel.tag DATELABEL_TAG;  
  34.         [cell.contentView addSubview: dateLabel];  
  35.    
  36.         //---top left---  
  37.         imageView_top_left [[[UIImageView alloc] init] autorelease];  
  38.         imageView_top_left.tag IMAGEVIEW_TAG_1;          
  39.         [cell.contentView addSubview: imageView_top_left];  
  40.    
  41.         //---top middle---  
  42.         imageView_top_middle [[[UIImageView alloc] init] autorelease];  
  43.         imageView_top_middle.tag IMAGEVIEW_TAG_2;  
  44.         [cell.contentView addSubview: imageView_top_middle];  
  45.    
  46.         //---top right---  
  47.         imageView_top_right [[[UIImageView alloc] init] autorelease];  
  48.         imageView_top_right.tag IMAGEVIEW_TAG_3;  
  49.         [cell.contentView addSubview: imageView_top_right];  
  50.    
  51.         //---middle left---  
  52.         imageView_middle_left [[[UIImageView alloc] init] autorelease];  
  53.         imageView_middle_left.tag IMAGEVIEW_TAG_4;  
  54.         [cell.contentView addSubview: imageView_middle_left];  
  55.    
  56.         //---middle middle---  
  57.         imageView_middle_middle [[[UIImageView alloc] init] autorelease];  
  58.         imageView_middle_middle.tag IMAGEVIEW_TAG_5;  
  59.         [cell.contentView addSubview: imageView_middle_middle];  
  60.    
  61.         //---middle right---  
  62.         imageView_middle_right [[[UIImageView alloc] init] autorelease];  
  63.         imageView_middle_right.tag IMAGEVIEW_TAG_6;  
  64.         [cell.contentView addSubview: imageView_middle_right];  
  65.    
  66.         //---bottom left---  
  67.         imageView_bottom_left [[[UIImageView alloc] init] autorelease];  
  68.         imageView_bottom_left.tag IMAGEVIEW_TAG_7;  
  69.         [cell.contentView addSubview: imageView_bottom_left];  
  70.    
  71.         //---bottom middle---  
  72.         imageView_bottom_middle [[[UIImageView alloc] init] autorelease];  
  73.         imageView_bottom_middle.tag IMAGEVIEW_TAG_8;  
  74.         [cell.contentView addSubview: imageView_bottom_middle];  
  75.    
  76.         //---bottom right---  
  77.         imageView_bottom_right [[[UIImageView alloc] init] autorelease];  
  78.         imageView_bottom_right.tag IMAGEVIEW_TAG_9;  
  79.         [cell.contentView addSubview: imageView_bottom_right];  
  80.    
  81.         //---message---  
  82.         messageLabel [[[UILabel alloc] init] autorelease];  
  83.         messageLabel.tag MESSAGELABEL_TAG;          
  84.         [cell.contentView addSubview: messageLabel];  
  85.    
  86.         //---set the images to display for each UIImageView---  
  87.         imageView_top_left.image   
  88.             [UIImage imageNamed:@"bubble_top_left.png"];  
  89.         imageView_top_middle.image   
  90.             [UIImage imageNamed:@"bubble_top_middle.png"];  
  91.         imageView_top_right.image   
  92.             [UIImage imageNamed:@"bubble_top_right.png"];  
  93.    
  94.         imageView_middle_left.image   
  95.             [UIImage imageNamed:@"bubble_middle_left.png"];  
  96.         imageView_middle_middle.image   
  97.             [UIImage imageNamed:@"bubble_middle_middle.png"];  
  98.         imageView_middle_right.image   
  99.             [UIImage imageNamed:@"bubble_middle_right.png"];  
  100.    
  101.         imageView_bottom_left.image   
  102.             [UIImage imageNamed:@"bubble_bottom_left.png"];  
  103.         imageView_bottom_middle.image   
  104.             [UIImage imageNamed:@"bubble_bottom_middle.png"];  
  105.         imageView_bottom_right.image   
  106.             [UIImage imageNamed:@"bubble_bottom_right.png"];          
  107.    
  108.     else          
  109.         //---reuse the old views---          
  110.        dateLabel (UILabel*)[cell.contentView viewWithTag: DATELABEL_TAG];  
  111.        messageLabel (UILabel*)[cell.contentView viewWithTag: MESSAGELABEL_TAG];          
  112.    
  113.         imageView_top_left   
  114.             (UIImageView*)[cell.contentView viewWithTag: IMAGEVIEW_TAG_1];  
  115.         imageView_top_middle   
  116.             (UIImageView*)[cell.contentView viewWithTag: IMAGEVIEW_TAG_2];  
  117.         imageView_top_right   
  118.             (UIImageView*)[cell.contentView viewWithTag: IMAGEVIEW_TAG_3];  
  119.    
  120.         imageView_middle_left   
  121.             (UIImageView*)[cell.contentView viewWithTag: IMAGEVIEW_TAG_4];  
  122.         imageView_middle_middle   
  123.             (UIImageView*)[cell.contentView viewWithTag: IMAGEVIEW_TAG_5];  
  124.         imageView_middle_right   
  125.             (UIImageView*)[cell.contentView viewWithTag: IMAGEVIEW_TAG_6];  
  126.    
  127.         imageView_bottom_left   
  128.             (UIImageView*)[cell.contentView viewWithTag: IMAGEVIEW_TAG_7];  
  129.         imageView_bottom_middle   
  130.             (UIImageView*)[cell.contentView viewWithTag: IMAGEVIEW_TAG_8];  
  131.         imageView_bottom_right   
  132.             (UIImageView*)[cell.contentView viewWithTag: IMAGEVIEW_TAG_9];                  
  133.      
  134.    
  135.     //---calculate the height for the label---  
  136.     int labelHeight [self labelHeight:[listOfMessages objectAtIndex:indexPath.row]];  
  137.     labelHeight -= bubbleFragment_height;  
  138.     if (labelHeight<0) labelHeight 0;     
  139.    
  140.     //---you can customize the look and feel for the date for each message here---  
  141.     dateLabel.frame CGRectMake(0.0, 0.0, 200, 15.0);  
  142.     dateLabel.font [UIFont boldSystemFontOfSize: FONTSIZE];  
  143.     dateLabel.textAlignment UITextAlignmentLeft;  
  144.     dateLabel.textColor [UIColor darkGrayColor];  
  145.     dateLabel.backgroundColor [UIColor clearColor];  
  146.    
  147.     //---top left---  
  148.     imageView_top_left.frame   
  149.         CGRectMake(bubble_x, bubble_y, bubbleFragment_width, bubbleFragment_height);          
  150.     //---top middle---  
  151.     imageView_top_middle.frame   
  152.         CGRectMake(bubble_x bubbleFragment_width, bubble_y,   
  153.                    bubbleFragment_width, bubbleFragment_height);          
  154.     //---top right---  
  155.     imageView_top_right.frame   
  156.         CGRectMake(bubble_x (bubbleFragment_width 2), bubble_y,   
  157.                    bubbleFragment_width, bubbleFragment_height);          
  158.     //---middle left---  
  159.     imageView_middle_left.frame   
  160.         CGRectMake(bubble_x, bubble_y bubbleFragment_height,   
  161.                    bubbleFragment_width, labelHeight);          
  162.     //---middle middle---  
  163.     imageView_middle_middle.frame   
  164.         CGRectMake(bubble_x bubbleFragment_width, bubble_y bubbleFragment_height,   
  165.                    bubbleFragment_width, labelHeight);          
  166.     //---middle right---  
  167.     imageView_middle_right.frame   
  168.         CGRectMake(bubble_x (bubbleFragment_width 2),   
  169.                    bubble_y bubbleFragment_height,   
  170.                    bubbleFragment_width, labelHeight);          
  171.     //---bottom left---  
  172.     imageView_bottom_left.frame   
  173.         CGRectMake(bubble_x, bubble_y bubbleFragment_height labelHeight,   
  174.                    bubbleFragment_width, bubbleFragment_height );           
  175.     //---bottom middle---  
  176.     imageView_bottom_middle.frame   
  177.         CGRectMake(bubble_x bubbleFragment_width,   
  178.                    bubble_y bubbleFragment_height labelHeight,  
  179.                    bubbleFragment_width, bubbleFragment_height);          
  180.     //---bottom right---  
  181.     imageView_bottom_right.frame   
  182.         CGRectMake(bubble_x (bubbleFragment_width 2),   
  183.                    bubble_y bubbleFragment_height labelHeight,   
  184.                    bubbleFragment_width, bubbleFragment_height );  
  185.    
  186.     //---you can customize the look and feel for each message here---      
  187.     messageLabel.frame   
  188.         CGRectMake(bubble_x 10, bubble_y 5,   
  189.                   (bubbleFragment_width 3) 25,   
  190.                   (bubbleFragment_height 2) labelHeight 10);  
  191.    
  192.     messageLabel.font [UIFont systemFontOfSize:FONTSIZE];          
  193.     messageLabel.textAlignment UITextAlignmentCenter;  
  194.     messageLabel.textColor [UIColor darkTextColor];  
  195.     messageLabel.numberOfLines 0; //---display multiple lines---  
  196.     messageLabel.backgroundColor [UIColor clearColor];  
  197.     messageLabel.lineBreakMode UILineBreakModeWordWrap;          
  198.    
  199.     dateLabel.text [dateOfMessages objectAtIndex:indexPath.row];  
  200.     messageLabel.text [listOfMessages objectAtIndex:indexPath.row];      
  201.     //--------------  
  202.    
  203.     return cell;  
  204.  
 

 

这个方法看起来很长,但是读起来却是一目了然。下面的伪代码展示它的主要逻辑:

viewplaincopyto clipboardprint?
  1. if (cell == nil)  
  2.      //---create and instantiate all the Label and UIImageView views---  
  3.      //---then add them to the cell---  
  4.   
  5.  else          
  6.      //---reuse the old views previously added to the cell---          
  7.   
  8.  //---customize the size, font, etc of all the views in the cell---  
 

 

其实就是由UIImageView与LabelView构造成了消息气泡. 总共有9个UIImageView,每一个就是那张气泡图片的一部份。把这些view再放在cell里,这个cell就是UITableViewCell类的一个例。当用户滚动TableView的时候,为了让离屏的view能重复利用,我们在加入cell的时候就加入了tag标志,如下:

viewplaincopyto clipboardprint?
  1. messageLabel.tag MESSAGELABEL_TAG;  
 

 

当你要重复用view的时候,你只需要像下面一样的方法就可以得到它:

viewplaincopyto clipboardprint?
  1. messageLabel (UILabel*)[cell.contentView viewWithTag: MESSAGELABEL_TAG];  
 

 

当用户点击了add按钮,就需要将消息加入到listOfMessages这个数组中,并通知TableView重新加载。相应的你也要把当前时间加到dateOfMessage这个数组当中:

viewplaincopyto clipboardprint?
  1. //---add message to the table view---  
  2. -(IBAction) btnAdd:(id) sender  
  3.     [listOfMessages addObject:itemName.text];      
  4.     [dateOfMessages addObject:[NSString stringWithFormat:@"%@",[NSDate date]]];  
  5.     [self.tableView reloadData];  
  6.  
 

 

最后, release这两个数组:

viewplaincopyto clipboardprint?
  1. (void)dealloc  
  2.     [listOfMessages release];  
  3.     [dateOfMessages release];       
  4.     [super dealloc];  
  5.  
 

 

按Commond+R在iPhone模拟器上运行,图12是程序的最终效果:

图12

 

 

 

总结


在本文中,你可以学到如何创建一个smsUI风格的应用程序。你可以修改代码,可以修改气泡的颜色,形状与大小。最重要的是,它可以让你的应用程序更加有趣,更具人性化。


原创粉丝点击