天天看點

swift 純代碼自定義cell(qq聊天界面)

本人也是初學者,如有錯誤,請指正~

網上大多數都是oc語言的例子,swift的比較少,我就寫一篇抛磚引玉

先放張效果圖

swift 純代碼自定義cell(qq聊天界面)

感覺做起來比Android麻煩百倍,文本高度要自己計算,cell行高也要自己計算。(Android裡面一個wrap_content就都解決了)

為什麼不用xib自定義呢,我表示那個情況下更加複雜,高度更不知道如何計算、還有圖檔拉伸的問題、

開始正文:

1.導入圖檔,plist檔案,字典轉模型

import UIKit

class Msg: NSObject {

    var text :String!
    var time :String!
    var type :NSNumber!

    override init() {
        super.init()
    }

    init(dir : Dictionary<String,AnyObject>) {
        super.init()
        setValuesForKeysWithDictionary(dir)
    }

    func getMsgArray() -> Array<Msg> {

        var array : Array<Msg> = []
        //取到plist檔案路徑
        let diaryList:String = NSBundle.mainBundle().pathForResource("messages", ofType:"plist")!
        //取出plist檔案資料
        let arraylist = NSMutableArray(contentsOfFile: diaryList)!

        for i in arraylist {
            let msg = Msg(dir: i as! Dictionary<String, AnyObject> )
            array.append(msg)

        }

        return array

    }

}
           

這裡也弄了很久,oc裡面是沒有Array,隻有NSArray,兩者差別大的很,Array很像Java裡面的ArrayList,需要加泛型,并且是一個結構體。關鍵方法setValuesForKeysWithDictionary、模型類的變量類型和名字都必須和plist檔案一緻!

2.建立自定義cell 繼承UITableViewCell

下面按照純代碼自定義cell的方式一步步建立

2.1聲明變量,并且初始化

import UIKit

class MsgCodeCell: UITableViewCell {

    var textmsg :UIButton?
    var icon :UIImageView?
    var time :UILabel?
    var screenWdith : CGFloat?

    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code 

        //xib自定義cell

    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        //代碼自定義cell的入口方法~

        textmsg = UIButton();
        icon = UIImageView();
        time = UILabel();
        //這裡做一些基本屬性設定

        time?.bounds = CGRect(x: 0, y: 0, width: 80, height: 10)
        time?.font = UIFont.boldSystemFontOfSize(12)

        screenWdith = UIScreen.mainScreen().bounds.size.width

        //先不設定frame和content
        contentView.addSubview(textmsg!)
        contentView.addSubview(icon!)
        contentView.addSubview(time!)
    }



           

初始化後,進行一些基本屬性的設定,如字型,一些已經可以确定的位置大小,具體的位置需要等到外部資料指派進來才能确定。

3.提供外部方法設定cell内容和内部控件位置

func setMsgModle(msg:Msg) {

        //設定時間
        time?.text = msg.time
        time?.center = CGPoint(x: contentView.center.x, y: )

        //設定頭像

        var textX : CGFloat = 
        var iconX : CGFloat = 
        var backimage : UIImage!

        //計算文字寬高!
        let size = NSString(string: msg.text).boundingRectWithSize(CGSizeMake(screenWdith!-, CGFloat(MAXFLOAT)), options: NSStringDrawingOptions.UsesLineFragmentOrigin , attributes: [NSFontAttributeName:UIFont.boldSystemFontOfSize()], context: nil).size

        if msg.type ==  {
            //發送者
            iconX = screenWdith! - 
            icon?.image = UIImage(named: "me")
            textX = screenWdith! - size.width-
            backimage = UIImage(named: "chat_send_nor")
        }else{
            //接收者
            iconX = 
            icon?.image = UIImage(named: "other")
            backimage = UIImage(named: "chat_recive_press_pic")
            textX = 
        }

        icon?.frame = CGRect(x: iconX, y: , width: , height: )

        //設定正文

        //設定button顯示

        textmsg?.setTitle(msg.text, forState: UIControlState.Normal)
        textmsg?.frame = CGRect(x: textX, y: , width: size.width+, height: size.height+)
        textmsg?.titleLabel?.font = UIFont.boldSystemFontOfSize()
        textmsg?.titleLabel?.numberOfLines=
        textmsg?.contentEdgeInsets = UIEdgeInsetsMake(,, , );


        let inset = UIEdgeInsets(top: (backimage?.size.height)!* , left: (backimage?.size.width)!*, bottom: (backimage?.size.height)!*, right: (backimage?.size.width)!*)

        let newimage =  backimage?.resizableImageWithCapInsets(inset)

        textmsg?.setBackgroundImage(newimage, forState: UIControlState.Normal)


    }
           

這裡關鍵是文字寬高的計算,和文字背景圖檔拉伸計算、(這裡最好不要用label來顯示正文,因為label要設定背景圖檔的話,會比較麻煩,是以這邊是用button來做的、)

關鍵代碼:

首先,String對象是沒有這個方法,先轉成NSString,調用boundingRectWithSize,第一個參數是文字所能接受的最大寬高,類型是CGSize,這邊的意思是寬度最大是 螢幕寬度-140 (為何減去140? 這裡頭像算50 ,然後間隙 都是 10 ,兩邊頭像加間隙 10+50+10 +10+50+10),高度最大表示換行、第二個參數是繪制屬性(不清楚),第三個是字型屬性,這裡可以傳字型大小,字型類型等等

let inset = UIEdgeInsets(top: (backimage?.size.height)!* , left: (backimage?.size.width)!*, bottom: (backimage?.size.height)!*, right: (backimage?.size.width)!*)

        let newimage =  backimage?.resizableImageWithCapInsets(inset)
           

這裡做圖檔拉伸,表示的是隻有中間拉伸,四周不變~(和.9圖檔一個意思)

好的,這裡自定義cell基本完了

3.計算行高

即文字高度和頭像高度中的最大值

在tableview中寫代理方法

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {

        var rowheight :CGFloat = 

        let msg = array[indexPath.row]

        //計算文字寬高!
        let size = NSString(string: msg.text).boundingRectWithSize(CGSizeMake(screenWdith!-, CGFloat(MAXFLOAT)), options: NSStringDrawingOptions.UsesLineFragmentOrigin , attributes: [NSFontAttributeName:UIFont.boldSystemFontOfSize()], context: nil).size


        //4.計算總高!

        if size.height > {
            // 字的高度
            rowheight = size.height+
        }else{
            //圖檔的高度
            rowheight = 
        }

        return rowheight
    }

           

4.重用cell

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

        //這裡做自定義cell重用

        var cell = tableView.dequeueReusableCellWithIdentifier("cell")

        if cell == nil {

            cell = MsgCodeCell(style: UITableViewCellStyle.Default , reuseIdentifier: "cell")
            cell!.selectionStyle = UITableViewCellSelectionStyle.None

            NSLog("初始化cell")
        }

       (cell as! MsgCodeCell).setMsgModle(array[indexPath.row])

        return cell!
    }
           

至此,cell是做完了~·~