日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Swift - 自定义单元格实现微信聊天界面

發(fā)布時間:2023/12/9 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Swift - 自定义单元格实现微信聊天界面 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

1,下面是一個放微信聊天界面的消息展示列表,實現(xiàn)的功能有:

(1)消息可以是文本消息也可以是圖片消息 (2)消息背景為氣泡狀圖片,同時消息氣泡可根據(jù)內(nèi)容自適應(yīng)大小 (3)每條消息旁邊有頭像,在左邊表示發(fā)送方,在右邊表示接收方
2,實現(xiàn)思路 (1)需要定義一個數(shù)據(jù)結(jié)構(gòu)保存消息內(nèi)容?MessageItem (2)繼承UITableViewCell實現(xiàn)自定義單元格,這里面放入頭像和消息體 (3)繼承UITableView實現(xiàn)自定義表格,通過讀取數(shù)據(jù)源,進行頁面的渲染 (4)消息體根據(jù)內(nèi)容類型不同,用不同的展示方法 (5)每個單元格的高度需要根據(jù)內(nèi)容計算出來 (6)數(shù)據(jù)由ViewController來提供初始化數(shù)據(jù)
3,效果圖

4,代碼結(jié)構(gòu)
5,主要代碼 (1)主頁面?ViewController.swift
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 import UIKit class ViewController: UIViewController, ChatDataSource { ????? ????var Chats:Array<MessageItem>! ????var tableView:TableView! ????? ????override func viewDidLoad() { ????????super.viewDidLoad() ????????// Do any additional setup after loading the view, typically from a nib. ????????? ????????setupChatTable() ????} ????? ????/*創(chuàng)建表格及數(shù)據(jù)*/ ????func setupChatTable() ????{ ????????self.tableView = TableView(frame:CGRectMake(0, 20, ????????????self.view.frame.size.width, self.view.frame.size.height - 20)) ????????? ????????//創(chuàng)建一個重用的單元格 ????????self.tableView!.registerClass(TableViewCell.self, forCellReuseIdentifier: "MsgCell") ????????? ????????var me = "xiaoming.png" ????????? ????????var you = "xiaohua.png" ????????? ????????var first =? MessageItem(body:"嘿,這張照片咋樣,我周末拍的呢!", logo:me, ????????????date:NSDate(timeIntervalSinceNow:-600), mtype:ChatType.Mine) ????????? ????????? ????????var second =? MessageItem(image:UIImage(named:"luguhu.jpeg")!,logo:me, ????????????date:NSDate(timeIntervalSinceNow:-290), mtype:ChatType.Mine) ????????? ????????var third =? MessageItem(body:"太贊了,我也想去那看看呢!",logo:you, ????????????date:NSDate(timeIntervalSinceNow:-60), mtype:ChatType.Someone) ????????? ?????????var fouth =? MessageItem(body:"嗯,下次我們一起去吧!",logo:me, ????????????date:NSDate(timeIntervalSinceNow:-20), mtype:ChatType.Mine) ????????? ????????var fifth =? MessageItem(body:"好的,一定!",logo:you, ????????????date:NSDate(timeIntervalSinceNow:0), mtype:ChatType.Someone) ????????? ????????Chats = [first,second, third, fouth, fifth] ????????? ????????self.tableView.chatDataSource = self ????????? ????? ????????self.tableView.reloadData() ????????? ????????self.view.addSubview(self.tableView) ????} ????override func didReceiveMemoryWarning() { ????????super.didReceiveMemoryWarning() ????????// Dispose of any resources that can be recreated. ????} ????/*返回對話記錄中的全部行數(shù)*/ ????func rowsForChatTable(tableView:TableView) -> Int ????{ ????????return self.Chats.count ????} ????? ????/*返回某一行的內(nèi)容*/ ????func chatTableView(tableView:TableView, dataForRow row:Int) -> MessageItem ????{ ????????return Chats[row] ????} }


(2)消息體數(shù)據(jù)結(jié)構(gòu) MessageItem.swift

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 import UIKit //消息類型,我的還是別人的 enum ChatType { ????case Mine ????case Someone } class MessageItem { ????//頭像 ????var logo:String ????//消息時間 ????var date:NSDate ????//消息類型 ????var mtype:ChatType ????//內(nèi)容視圖,標簽或者圖片 ????var view:UIView ????//邊距 ????var insets:UIEdgeInsets ????? ????//設(shè)置我的文本消息邊距 ????class func getTextInsetsMine() -> UIEdgeInsets ????{ ????????return UIEdgeInsets(top:5, left:10, bottom:11, right:17) ????} ????? ????//設(shè)置他人的文本消息邊距 ????class func getTextInsetsSomeone() -> UIEdgeInsets ????{ ????????return UIEdgeInsets(top:5, left:15, bottom:11, right:10) ????} ????? ????//設(shè)置我的圖片消息邊距 ????class func getImageInsetsMine() -> UIEdgeInsets ????{ ????????return UIEdgeInsets(top:11, left:13, bottom:16, right:22) ????} ????? ????//設(shè)置他人的圖片消息邊距 ????class func getImageInsetsSomeone() -> UIEdgeInsets ????{ ????????return UIEdgeInsets(top:11, left:13, bottom:16, right:22) ????} ????? ????//構(gòu)造文本消息體 ????convenience init(body:NSString, logo:String, date:NSDate, mtype:ChatType) ????{ ????????var font =? UIFont.boldSystemFontOfSize(12) ????????? ????????var width =? 225, height = 10000.0 ????????? ????????var atts =? NSMutableDictionary() ????????atts.setObject(font,forKey:NSFontAttributeName) ????????? ????????var size =? body.boundingRectWithSize(CGSizeMake(CGFloat(width), CGFloat(height)), ????????????options:NSStringDrawingOptions.UsesLineFragmentOrigin, attributes:atts, context:nil) ????????? ????????var label =? UILabel(frame:CGRectMake(0, 0, size.size.width, size.size.height)) ????????? ????????label.numberOfLines = 0 ????????label.lineBreakMode = NSLineBreakMode.ByWordWrapping ????????label.text = (body.length != 0 ? body : "") ????????label.font = font ????????label.backgroundColor = UIColor.clearColor() ????????? ????????var insets:UIEdgeInsets =? (mtype == ChatType.Mine ? ????????????MessageItem.getTextInsetsMine() : MessageItem.getTextInsetsSomeone()) ????????? ????????self.init(logo:logo, date:date, mtype:mtype, view:label, insets:insets) ????} ????? ????//可以傳入更多的自定義視圖 ????init(logo:String, date:NSDate, mtype:ChatType, view:UIView, insets:UIEdgeInsets) ????{ ????????self.view = view ????????self.logo = logo ????????self.date = date ????????self.mtype = mtype ????????self.insets = insets ????} ????? ????//構(gòu)造圖片消息體 ????convenience init(image:UIImage, logo:String,? date:NSDate, mtype:ChatType) ????{ ????????var size = image.size ????????//等比縮放 ????????if (size.width > 220) ????????{ ????????????size.height /= (size.width / 220); ????????????size.width = 220; ????????} ????????var imageView = UIImageView(frame:CGRectMake(0, 0, size.width, size.height)) ????????imageView.image = image ????????imageView.layer.cornerRadius = 5.0 ????????imageView.layer.masksToBounds = true ????????? ????????var insets:UIEdgeInsets =? (mtype == ChatType.Mine ? ????????????MessageItem.getImageInsetsMine() : MessageItem.getImageInsetsSomeone()) ????????? ????????self.init(logo:logo,? date:date, mtype:mtype, view:imageView, insets:insets) ????}??? }


(3)表格數(shù)據(jù)協(xié)議 ChatDataSource.swift

1 2 3 4 5 6 7 8 9 10 11 12 import Foundation /* ??數(shù)據(jù)提供協(xié)議 */ protocol ChatDataSource {?? ????/*返回對話記錄中的全部行數(shù)*/ ????func rowsForChatTable( tableView:TableView) -> Int ????/*返回某一行的內(nèi)容*/ ????func chatTableView(tableView:TableView, dataForRow:Int)-> MessageItem }


(4)自定義表格 TableView.swift

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 import UIKit class TableView:UITableView,UITableViewDelegate, UITableViewDataSource { ????//用于保存所有消息 ????var bubbleSection:Array<MessageItem>! ????//數(shù)據(jù)源,用于與 ViewController 交換數(shù)據(jù) ????var chatDataSource:ChatDataSource! ????? ????required init(coder aDecoder: NSCoder) { ???????? ????????super.init(coder: aDecoder) ????} ????? ????override init(frame:CGRect) ????{ ????????self.bubbleSection = Array<MessageItem>() ????????? ????????super.init(frame:frame,? style:UITableViewStyle.Grouped) ????????? ????????self.backgroundColor = UIColor.clearColor() ????????? ????????self.separatorStyle = UITableViewCellSeparatorStyle.None ????????self.delegate = self ????????self.dataSource = self ????????? ????????? ????} ????? ????override func reloadData() ????{ ????????? ????????self.showsVerticalScrollIndicator = false ????????self.showsHorizontalScrollIndicator = false ????????? ????????var count =? 0 ????????if ((self.chatDataSource != nil)) ????????{ ????????????count = self.chatDataSource.rowsForChatTable(self) ????????????? ????????????if(count > 0) ????????????{?? ????????????????? ????????????????for (var i = 0; i < count; i++) ????????????????{ ????????????????????? ????????????????????var object =? self.chatDataSource.chatTableView(self, dataForRow:i) ????????????????????bubbleSection.append(object) ????????????????????? ????????????????} ????????????????? ????????????????//按日期排序方法 ????????????????bubbleSection.sort({$0.date.timeIntervalSince1970 < $1.date.timeIntervalSince1970}) ????????????} ????????} ????????super.reloadData() ????} ????? ????//第一個方法返回分區(qū)數(shù),在本例中,就是1 ????func numberOfSectionsInTableView(tableView:UITableView)->Int ????{ ????????return 1 ????} ????? ????//返回指定分區(qū)的行數(shù) ????func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int ????{ ????????if (section >= self.bubbleSection.count) ????????{ ????????????return 1 ????????} ????????? ????????return self.bubbleSection.count+1 ????} ????????? ????//用于確定單元格的高度,如果此方法實現(xiàn)得不對,單元格與單元格之間會錯位 ????func tableView(tableView:UITableView,heightForRowAtIndexPath indexPath:NSIndexPath) -> CGFloat ????{ ????????? ????????// Header ????????if (indexPath.row == 0) ????????{ ????????????return 30.0 ????????} ????????? ????????var data =? self.bubbleSection[indexPath.row - 1] ????????? ????????return max(data.insets.top + data.view.frame.size.height + data.insets.bottom, 52) ????} ????? ????//返回自定義的 TableViewCell ????func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) ????????-> UITableViewCell ????{ ??????????? ????????var cellId = "MsgCell" ????????if(indexPath.row > 0) ????????{ ????????????var data =? self.bubbleSection[indexPath.row-1] ????????? ????????????var cell =? TableViewCell(data:data, reuseIdentifier:cellId) ????????? ????????????return cell ????????} ????????else ????????{ ????????????? ????????????return UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: cellId) ????????} ????} }


(5)自定義單元格 TableViewCell.swift

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 import UIKit class TableViewCell:UITableViewCell { ????//消息內(nèi)容視圖 ????var customView:UIView! ????//消息背景 ????var bubbleImage:UIImageView! ????//頭像 ????var avatarImage:UIImageView! ????//消息數(shù)據(jù)結(jié)構(gòu) ????var msgItem:MessageItem! ????? ????required init(coder aDecoder: NSCoder) { ????????? ????????super.init(coder: aDecoder) ????} ????? ????//- (void) setupInternalData ????init(data:MessageItem, reuseIdentifier cellId:String) ????{ ????????self.msgItem = data ????????super.init(style: UITableViewCellStyle.Default, reuseIdentifier:cellId) ????????rebuildUserInterface() ????} ????? ????func rebuildUserInterface() ????{ ????????? ????????self.selectionStyle = UITableViewCellSelectionStyle.None ????????if (self.bubbleImage == nil) ????????{ ????????????self.bubbleImage = UIImageView() ????????????self.addSubview(self.bubbleImage) ????????????? ????????} ????????? ????????var type =? self.msgItem.mtype ????????var width =? self.msgItem.view.frame.size.width ????????? ????????var height =? self.msgItem.view.frame.size.height ????????? ????????var x =? (type == ChatType.Someone) ? 0 : self.frame.size.width - width - ????????????self.msgItem.insets.left - self.msgItem.insets.right ????????? ????????var y:CGFloat =? 0 ????????//顯示用戶頭像 ????????if (self.msgItem.logo != "") ????????{ ????????????? ????????????var logo =? self.msgItem.logo ????????????? ????????????self.avatarImage = UIImageView(image:UIImage(named:(logo != "" ? logo : "noAvatar.png"))) ????????????? ????????????self.avatarImage.layer.cornerRadius = 9.0 ????????????self.avatarImage.layer.masksToBounds = true ????????????self.avatarImage.layer.borderColor = UIColor(white:0.0 ,alpha:0.2).CGColor ????????????self.avatarImage.layer.borderWidth = 1.0 ????????????? ????????????//別人頭像,在左邊,我的頭像在右邊 ????????????var avatarX =? (type == ChatType.Someone) ? 2 : self.frame.size.width - 52 ????????????? ????????????//頭像居于消息底部 ????????????var avatarY =? height ????????????//set the frame correctly ????????????self.avatarImage.frame = CGRectMake(avatarX, avatarY, 50, 50) ????????????self.addSubview(self.avatarImage) ????????????? ????????????? ????????????var delta =? self.frame.size.height - (self.msgItem.insets.top + self.msgItem.insets.bottom ????????????????+ self.msgItem.view.frame.size.height) ????????????if (delta > 0) ????????????{ ????????????????y = delta ????????????} ????????????if (type == ChatType.Someone) ????????????{ ????????????????x += 54 ????????????} ????????????if (type == ChatType.Mine) ????????????{ ????????????????x -= 54 ????????????} ????????} ????????? ????????self.customView = self.msgItem.view ????????self.customView.frame = CGRectMake(x + self.msgItem.insets.left, y ????????????+ self.msgItem.insets.top, width, height) ????????? ????????self.addSubview(self.customView) ????????? ????????//如果是別人的消息,在左邊,如果是我輸入的消息,在右邊 ????????if (type == ChatType.Someone) ????????{ ????????????self.bubbleImage.image = ????????????????UIImage(named:("yoububble.png"))!.stretchableImageWithLeftCapWidth(21,topCapHeight:14) ????????????? ????????} ????????else { ????????????self.bubbleImage.image = ????????????????UIImage(named:"mebubble.png")!.stretchableImageWithLeftCapWidth(15, topCapHeight:14) ????????} ????????self.bubbleImage.frame = CGRectMake(x, y, width + self.msgItem.insets.left ????????????+ self.msgItem.insets.right, height + self.msgItem.insets.top + self.msgItem.insets.bottom) ????} }


6,源碼下載:WeiXinChart.zip?


7,功能改進版下載:WeiXinChart_advance.zip (1)消息按天分組展示 (2)增加消息發(fā)送框,可以發(fā)送和展示消息

? ?

總結(jié)

以上是生活随笔為你收集整理的Swift - 自定义单元格实现微信聊天界面的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。