zoukankan      html  css  js  c++  java
  • 聊天界面之气泡文本cell(一)

    在实现qq聊天界面的过程中,使用UITableViewCell碰到了不少问题,这里还是记录一下以免遗忘。

    气泡聊天cell的实现,网上最多的方法还是:

    1.手动计算设置frame的值,文本的size使用boundingRectWithSize函数动态计算

    2.气泡的实现,拉伸使用resizableImageWithCapInsets函数,还需要设置文本UILabel的frame在气泡之内

    因为后来发现tableView在绘制cell时是先询问高度,再询问cell,可是询问高度时cell还未计算,如果先计算一遍高度的话效率上又不划算,

    这种方案多少还是不完善,最后也未采用,所以直接贴出代码作为参考。

    class ChatTableViewCell: UITableViewCell {
        
        @IBOutlet weak var bubbleImage: UIImageView!
        @IBOutlet weak var time: UILabel!
        @IBOutlet weak var icon: UIImageView!
        @IBOutlet weak var content: UILabel!
        
        var height:CGFloat!
        
        class func initChatCell(tableView:UITableView,message:TextMessage,iconname:String) -> ChatTableViewCell?{
            
            var t:UITableViewCell? = tableView.dequeueReusableCellWithIdentifier("ChatTableViewCell")
            
            if t == nil{
                t = NSBundle.mainBundle().loadNibNamed("ChatTableViewCell", owner: nil, options: nil).first as? UITableViewCell
            }
            let cell:ChatTableViewCell = t as! ChatTableViewCell
           
            // 屏幕的宽度
            let screenW = UIScreen.mainScreen().bounds.width
            let paddingSize:CGFloat = 5
            let timeHided = false
    
            if timeHided{
               cell.time.frame = CGRectMake(0,0, 0, 0)
               cell.time.hidden = true
            }else{
                cell.time.textAlignment = NSTextAlignment.Center
                cell.time.textColor = UIColor.darkGrayColor()
                cell.time.font = UIFont.systemFontOfSize(13)
                cell.time.text = message.time
                cell.time.frame = CGRectMake(0,paddingSize,screenW,20)
            }
            cell.time.layoutIfNeeded()
            
            let timeH = cell.time.frame.maxY + paddingSize
            let iconSize:CGFloat = 40
            let bubble_insets = (message.role == Role.Me ? UIEdgeInsetsMake(15,20,15,23):UIEdgeInsetsMake(15,23,15,20))
            let iconExtendWith = iconSize+paddingSize
            
            
            let textString = NSString(string: message.text ?? "")
            let size = CGSizeMake(screenW-iconExtendWith*2-bubble_insets.left-bubble_insets.right, CGFloat(MAXFLOAT))
            let attributes = [NSFontAttributeName: UIFont.systemFontOfSize(15)]
            let textSize = textString.boundingRectWithSize(size, options: NSStringDrawingOptions.UsesLineFragmentOrigin, attributes: attributes, context: nil)
            let bubbleWidth  =  textSize.width+bubble_insets.left+bubble_insets.right
            let bubbleHeight =  textSize.height+bubble_insets.top+bubble_insets.bottom
            var iconF:CGRect
            var bubbleF:CGRect
            var contentF:CGRect
            var bgImage:UIImage
            if message.role == Role.Me{
                iconF = CGRectMake(screenW-paddingSize-iconSize, timeH+bubble_insets.top*0.7,iconSize, iconSize)
                
                bubbleF = CGRectMake(iconF.origin.x-bubbleWidth-paddingSize,timeH,bubbleWidth,bubbleHeight)
                bgImage = UIImage(named:"chat_send_nor@2x")!
            }else{
                iconF = CGRectMake(paddingSize, timeH+bubble_insets.top*0.7,iconSize, iconSize)
                
                bubbleF = CGRectMake(iconF.maxX+paddingSize,timeH,bubbleWidth,bubbleHeight)
                bgImage = UIImage(named:"chat_recive_nor@2x")!
            }
            contentF = CGRectMake(bubbleF.origin.x+bubble_insets.left, bubbleF.origin.y+bubble_insets.top, textSize.width, textSize.height)
            
            cell.icon.image = UIImage(named:iconname)
            cell.icon.frame = iconF
            cell.icon.layoutIfNeeded()
            
            cell.content.font = UIFont.systemFontOfSize(15)
            cell.content.numberOfLines = 0
            cell.content.lineBreakMode = .ByWordWrapping
            cell.content.text = message.text
            cell.content.frame = contentF
            cell.content.layoutIfNeeded()
            
            let H = floor(bgImage.size.height*0.5)
            let W = floor(bgImage.size.width*0.5)
            let insets = UIEdgeInsetsMake(H, W, bgImage.size.height-H-1, bgImage.size.width-W-1)
            cell.bubbleImage.image = bgImage.resizableImageWithCapInsets(insets)
            cell.bubbleImage.frame = bubbleF
            cell.bubbleImage.layoutIfNeeded()
        
            cell.layoutIfNeeded()//需要在xib中禁用autolayout,layoutIfNeeded否则失效,cell第一次会按xib中的布局显示
            cell.height = max(cell.bubbleImage.frame.maxY,cell.icon.frame.maxY)
            
            return t as? ChatTableViewCell
        }
    
        override func awakeFromNib() {
            super.awakeFromNib()
            // Initialization code
            self.backgroundColor = UIColor.whiteColor()
        }
    
        override func setSelected(selected: Bool, animated: Bool) {
            super.setSelected(selected, animated: animated)
    
            // Configure the view for the selected state
        }
    //    override func layoutSubviews() {
    //        super.layoutSubviews()
    //    }
    }
    

      

    cell是在xib中实现的,需要注意的是:

    1.需要先拖bubbleImage,再拖uilabel,因为文字要显示在气泡之上。否则的话文字会被气泡覆盖掉

    2.需要在 xib中禁用autolayout,否则好像手动设置的frame,调用layoutIfNeeded不起作用。而约束又未设置,cell就会以初始布局显示。

    附上目前使用的三种类型的消息的定义:

    //
    //  Message.swift
    //  OrayTalk
    //
    //  Created by 梅利健 on 16/6/4.
    //  Copyright © 2016年 meilijian. All rights reserved.
    //
    
    import Foundation
    
    public enum Role:Int {
        case Me
        case Other
    }
    
    class BaseMessage:NSObject{
        var time:String!
        var text:String!
        override init() {
            super.init()
        }
        
        init(time:String,text:String) {
            self.time = time
            self.text = text
        }
    }
    
    class TextMessage:BaseMessage{
    
        var role:Role = Role.Me
    
        class func messageWithDic(dic:[String:AnyObject],role:Role) -> TextMessage{
            
            let message = TextMessage()
            
            message.setValuesForKeysWithDictionary(dic)
            message.role = role
            return message
            
        }
        override init() {
            super.init()
        }
        init(time:String,text:String,role:Role) {
            super.init(time: time,text: text)
            self.role = role
        }
    }
    
    class TipMessage: BaseMessage {
        
    }
    
    class ProgressMessage:BaseMessage{
        var role:Role = Role.Me
        var total: UInt64 = 0
        var transfered: UInt64 = 0
        var lastdate:NSDate =  NSDate()
        var lasttransfered: UInt64 = 0
        var speed:Double = 0
        init(time:String,text:String,role:Role) {
            super.init(time: time,text: text)
            self.role = role
        }
        
        var SpeedDescription:String{
            get{
                if speed >= 1024*1024{
                    return NSString(format: "%0.2fM/s", speed/(1024*1024)) as String
                }
                else if speed >= 1024{
                    return NSString(format: "%0.2fK/s", speed/(1024)) as String
                }
                else if speed >= 0{
                    return NSString(format: "%0.2fB/s", speed) as String
                }
                else{
                    return NSString(format: "%0.2fB/s", 0) as String
                }
            }
        }
    }
    

      

  • 相关阅读:
    Java并发基础-并发模型、基础接口以及Thread
    Java基础-IO
    大数据平台搭建-hbase集群的搭建
    大数据平台搭建-zookeeper集群的搭建
    大数据平台搭建-基础环境安装
    kafka知识体系-消费者编程实践
    kafka知识体系-生产者编程实践
    editplus打造java运行环境(安装、配置、操作)
    实验2 安装Atlas实现读写分离
    实验1 配置MySQL主从同步
  • 原文地址:https://www.cnblogs.com/mlj318/p/5836353.html
Copyright © 2011-2022 走看看