美文网首页
自定义单元格实现微信聊天界面

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

作者: 焉逢12 | 来源:发表于2017-03-07 14:30 被阅读0次
    屏幕快照 2017-03-07 下午2.24.10.png

    ViewController

    import UIKit
    
    class ViewController: UIViewController,chatDataSourch {
    
        var tableView :TableView!
        var messageArr :Array<messageModel>!
        
        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view, typically from a nib.
            
            buildTable()
            
            
            
            
        }
        func buildTable()
        {
            self.tableView = TableView(frame: CGRect(x: 0, y: 20, width: self.view.frame.size.width, height: self.view.frame.height-20), style: .plain)
            self.tableView.register(tableViewCell.self, forCellReuseIdentifier: "GPLcell")
            
            let me = "xiaoming.png"
            let you = "xiaohua.png"
            
            let first =  messageModel(body:"嘿,这张照片咋样,我周末拍的呢!", logo:me,
                                     date:NSDate(timeIntervalSinceNow:-600), mtype:chatType.Mine)
            
            let second = messageModel(img: UIImage(named:"luguhu.jpeg")!, logo: me, date: NSDate(timeIntervalSinceNow:-290), mtype: chatType.Mine)
            
            let third =  messageModel(body:"太赞了,我也想去那看看呢!",logo:you,
                                     date:NSDate(timeIntervalSinceNow:-60), mtype:chatType.Other)
            
            let fouth =  messageModel(body:"嗯,下次我们一起去吧!",logo:me,
                                     date:NSDate(timeIntervalSinceNow:-20), mtype:chatType.Mine)
            
            let fifth =  messageModel(body:"好的,一定!",logo:you,
                                     date:NSDate(timeIntervalSinceNow:0), mtype:chatType.Other)
            self.messageArr = [first,second,third,fouth,fifth]
            
            //数据协议
            //代理方法
            self.tableView.chatDataSource = self
            
            self.tableView.reloadData()
            self.view.addSubview(self.tableView)
            
        }
        //实现chatDataSourch代理方法
        func rowsForChatTable(tableView: TableView) -> Int {
            return self.messageArr.count
        }
        func chatTableView(tableView: TableView, dataForRow: Int) -> messageModel {
            return self.messageArr[dataForRow]
            
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
            // Dispose of any resources that can be recreated.
        }
    
    
    }
    
    

    messageModel

    import Foundation
    
    import UIKit
    
    //枚举,判断当前消息用户
    enum chatType
    {
        case Mine
        case Other
    }
    
    class messageModel {
        //头像
        var logo:String
        //日期
        var date:NSDate
        //消息类型
        var mytype :chatType
        //内容视图
        var view :UIView
        //边距
        var insets:UIEdgeInsets
        
        /*
         class func 类方法
         
         */
        //设置我的文本消息边距
        class func getTextInsetsMine() -> UIEdgeInsets {
            return UIEdgeInsets(top: 5, left: 10, bottom: 11, right: 17)
        }
        
        //设置他人的文本消息边距
        class func getTextInsetsSomeone() -> UIEdgeInsets {
            return UIEdgeInsets(top:5, left:15, bottom:11, right:10)
        }
        
        //设置我的图片消息边距
        class func getImageInsetsMine() -> UIEdgeInsets {
            return UIEdgeInsets(top:11, left:13, bottom:16, right:22)
        }
        
        //设置他人的图片消息边距
        class func getImageInsetsSomeone() -> UIEdgeInsets {
            return UIEdgeInsets(top:11, left:13, bottom:16, right:22)
        }
        init(logo:String, date:NSDate, mytype:chatType, view:UIView, insets:UIEdgeInsets) {
            self.view = view
            self.logo = logo
            self.date = date
            self.mytype = mytype
            self.insets = insets
        }
        /*
         convenience 优先级比较低
          所有的 convenience 初始化方法都必须调用同一个类中的 designated 初始化完成设置
         */
        //文字消息
        convenience init(body:NSString, logo:String, date:NSDate, mtype:chatType)
        {
            let font = UIFont.boldSystemFont(ofSize: 12)
            
            let width =  225.0, height = 10000.0
            
            let atts =  [NSFontAttributeName: font]
            
            //计算字符串的高度
            let size = body.boundingRect(with:CGSize(width: width, height: height), options: .usesLineFragmentOrigin, attributes: atts, context: nil)
            
            let label = UILabel(frame: CGRect(x: 0, y: 0, width: size.size.width, height: size.size.height))
            label.numberOfLines = 0
            label.lineBreakMode = NSLineBreakMode.byWordWrapping
            label.text = (body.length != 0 ? body as String : "")
            label.font = font
            label.backgroundColor = UIColor.clear
            
            let insets1:UIEdgeInsets =  (mtype == chatType.Mine ?
                messageModel.getTextInsetsMine() : messageModel.getTextInsetsSomeone())
    
            self.init(logo:logo,date:date,mytype:mtype,view:label,insets:insets1)
            
        }
        //图片消息
        convenience init(img:UIImage, logo:String, date:NSDate, mtype:chatType)
        {
            var size = img.size
            //等比缩放
            if size.width>220 {
                size.height = (size.height)/(size.width / 220)
                size.width=220
            }
            let imageView = UIImageView(frame:CGRect(x: 0, y: 0, width: size.width, height: size.height))
            imageView.image = img
            imageView.layer.cornerRadius = 5.0
            imageView.layer.masksToBounds = true
            
            let insets:UIEdgeInsets =  (mtype == chatType.Mine ?
                messageModel.getImageInsetsMine() : messageModel.getImageInsetsSomeone())
            
            self.init(logo:logo,date:date,mytype:mtype,view:imageView,insets:insets)
        }
        
        
        
    }
    

    chatDataSourch

    import Foundation
    import UIKit
    //数据协议
    protocol chatDataSourch
    {
        /*返回对话记录中的全部行数*/
        func rowsForChatTable( tableView:TableView) -> Int
        /*返回某一行的内容*/
        func chatTableView(tableView:TableView, dataForRow:Int)-> messageModel
    }
    /*
     
     protocol Student {
     //类方法
     static func study()
     //实例方法
     func changeName()
     }
     struct CollageStudent: Student {
     //类方法实现
     static func study() {
     }
     //实例方法实现
     func changeName() {
     }
     }
     //方法的调用
     CollageStudent.study()
     var c1 = CollageSt
     
     */
    

    tableViewCell

    import Foundation
    import UIKit
    
    class tableViewCell: UITableViewCell {
        //消息内容视图
        var customView:UIView!
        //消息背景
        var bubbleImage:UIImageView!
        //头像
        var avatarImage:UIImageView!
        //消息数据结构
        var msgModel:messageModel!
        
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
        }
        
        init(data:messageModel,reuseIdentifier cellId:String) {
            self.msgModel = data
            super.init(style: .default, reuseIdentifier: cellId)
            rebuildUserInterface()
        }
        func rebuildUserInterface()
        {
            self.selectionStyle = UITableViewCellSelectionStyle.none
            if (self.bubbleImage == nil)
            {
                self.bubbleImage = UIImageView()
                self.addSubview(self.bubbleImage)
            }
            let type =  self.msgModel.mytype
            let width =  self.msgModel.view.frame.size.width
            
            let height =  self.msgModel.view.frame.size.height
            
            var x =  (type == chatType.Other) ? 0 : self.frame.size.width - width -
                self.msgModel.insets.left - self.msgModel.insets.right
            
            var y:CGFloat =  0
            
            if self.msgModel.logo != ""
            {
                let logo =  self.msgModel.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
                
                //别人头像,在左边,我的头像在右边
                let avatarX =  (type == chatType.Other) ? 2 : self.frame.size.width - 52
                
                //头像居于消息底部
                let avatarY =  height
                //set the frame correctly
                self.avatarImage.frame = CGRect(x: avatarX, y: avatarY, width: 50, height: 50)
                self.addSubview(self.avatarImage)
                
                let delta =  self.frame.size.height - (self.msgModel.insets.top
                    + self.msgModel.insets.bottom + self.msgModel.view.frame.size.height)
                if (delta > 0) {
                    y = delta
                }
                if (type == chatType.Other) {
                    x += 54
                }
                if (type == chatType.Mine) {
                    x -= 54
                }
            }
            self.customView = self.msgModel.view
    
            self.customView.frame = CGRect(x: (x + self.msgModel.insets.left), y: (y + self.msgModel.insets.top),  width: width, height: height)
            
            self.addSubview(self.customView)
            
            //如果是别人的消息,在左边,如果是我输入的消息,在右边
            if (type == chatType.Other)
            {
                //拉伸图片
                self.bubbleImage.image = UIImage(named:("yoububble.png"))!
                    .stretchableImage(withLeftCapWidth: 21,topCapHeight:14)
                
            }
            else {
                self.bubbleImage.image = UIImage(named:"mebubble.png")!
                    .stretchableImage(withLeftCapWidth: 15, topCapHeight:14)
            }
    
            self.bubbleImage.frame = CGRect(x: x, y: y, width: (width + self.msgModel.insets.left + self.msgModel.insets.right), height: (height + self.msgModel.insets.top + self.msgModel.insets.bottom))
            
        }
        //让单元格宽度始终为屏幕宽
        override var frame: CGRect {
            get {
                return super.frame
            }
            set (newFrame) {
                var frame = newFrame
                frame.size.width = UIScreen.main.bounds.width
                super.frame = frame
            }
        }
            
    
        
        
        
    }
    

    TableView

    import Foundation
    import UIKit
    
    class TableView: UITableView,UITableViewDelegate,UITableViewDataSource {
        //存储消息
        var bubbleSection:Array<messageModel>!
        //数据源,用于与 ViewController 交换数据
        var chatDataSource:chatDataSourch!
        
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
        }
        
        //override覆盖  重写初始化方法
        override init(frame: CGRect, style: UITableViewStyle) {
            //初始化
            super.init(frame: frame, style: style)
            self.bubbleSection = Array<messageModel>()
            self.backgroundColor = UIColor.clear
            self.separatorStyle = UITableViewCellSeparatorStyle.none
            self.delegate = self
            self.dataSource = self
        }
        
        //重写reloadData方法
        override func reloadData() {
            //设置不显示滚动条
            self.showsVerticalScrollIndicator = false
            self.showsHorizontalScrollIndicator = false
            
            var count = 0
            if self.chatDataSource != nil {
                count = self.chatDataSource.rowsForChatTable(tableView: self)
                
                if count>0 {
                    for i in 0..<count {
                        let object = self.chatDataSource.chatTableView(tableView: self, dataForRow: i)
                        self.bubbleSection.append(object)
                    }
                    //按日期排序方法
                    bubbleSection.sort(by: {
                        $0.date.timeIntervalSince1970 < $1.date.timeIntervalSince1970
                    })
                }
            }
            super.reloadData()
        }
        //区数
        func numberOfSections(in tableView: UITableView) -> Int {
            return 1
        }
        
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            if (section >= self.bubbleSection.count)
            {
                return 0
            }
            
            return self.bubbleSection.count
        }
        
        //用于确定单元格的高度,如果此方法实现得不对,单元格与单元格之间会错位
        func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
            let data =  self.bubbleSection[indexPath.row]
            return max(data.insets.top + data.view.frame.size.height + data.insets.bottom, 52)
    
        }
    
        
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cellID = "GPLcell"
            let data = self.bubbleSection[indexPath.row]
            
            let cell = tableViewCell(data: data, reuseIdentifier: cellID)
            return cell
            
            
        }
            
        
    }
    

    相关文章

      网友评论

          本文标题:自定义单元格实现微信聊天界面

          本文链接:https://www.haomeiwen.com/subject/oosmgttx.html