TableViewCell嵌套TableView實(shí)現(xiàn)評論列表蓋樓效果

效果




tableView的使用時(shí)需要細(xì)心去優(yōu)化的,我這里就隨便做了一下,界面目前沒有卡頓現(xiàn)象。

如上圖,我的界面是ViewController中加了一個(gè)TableView,tableView分了兩組,第一組是顯示的問題,第二組顯示評論,現(xiàn)在實(shí)現(xiàn)的效果:直接點(diǎn)擊最下面回復(fù)則回復(fù)樓主,點(diǎn)第二組cell上的回復(fù)層主,層主樓層中的回復(fù)不能再被評論。

思路:

由于評論條數(shù),字?jǐn)?shù)未知,所以最外層tableViewcell高度不固定,里層tableViewcell高度也不固定,就需要用Autolayout來布局,在這里選擇用Snapkit做,在給里面的tableView布局時(shí)必須用 tableView.snp_removeConstraints()清空原來的約束,否則會沖突,當(dāng)然也可以用更新約束的方法,自己嘗試

嵌入的tableViewcell是系統(tǒng)自帶的,最外層tableViewcell定制如下

import UIKit

protocol WenCellStyleTwoDelegate:class {
    func huifuButtonClicked(touser_id:String,answer_id:String)
}
class WenWenDetailTableViewCellStyleTwo: UITableViewCell {

    //屬性
    weak var delegate: WenCellStyleTwoDelegate? = nil
    var headView:WenDetailcellHeadView!
    let titleLabel = UILabel()
    let tableView = UITableView()
    
    //tableViewCell高度數(shù)組
    var cellHeightArray = [CGFloat]()
    
    //數(shù)據(jù)源數(shù)組
    var childArray:NSArray? = nil{
        didSet{
            if childArray == nil {
                return
            }
            //計(jì)算本cell中tableView的cell高度
            cellHeightArray.removeAll()
            for item in childArray! {
                let model = item as! childModel
                let text = "\(model.mobile_phone)回復(fù)\(model.tomobile_phone):\(model.content)"
                let height = ToolManager.calculateStringSize(text, maxW: kScreen_W - 16, maxH: 10000, fontSize: 17).height
                cellHeightArray.append(height+10)
                //                print(cellHeightArray)
            }
            tableView.reloadData()
        }
    }
    
    var model:WenWenCellStyleTwoMode? = nil{
        didSet{
            if model == nil {
                return
            }
            if model?.child != nil {
                childArray = nil
                childArray = model!.child!
            }
            
            let url = NSURL(string: appURL+model!.head_img)
            headView.userHeadImageView.kf_setImageWithURL(url!, placeholderImage: nil)
            headView.userNameLabel.text = ToolManager.stringByX(model!.mobile_phone, startindex: 3, endindex: 7)
            headView.timeLabel.text = model!.timestuts
            
            titleLabel.text = model!.content
            
            setNeedsDisplay()
        }
    }
    
    override func awakeFromNib() {
        super.awakeFromNib()
    }
    
    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        
        creatUI()
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func setSelected(selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
    }

}

//MARK: - 界面相關(guān)
extension WenWenDetailTableViewCellStyleTwo{
    
    func creatUI(){
        contentView.backgroundColor = UIColor.whiteColor()
        
        let nib = UINib(nibName: "WenDetailcellHeadView", bundle: nil)
        headView = nib.instantiateWithOwner(self, options: nil).first as! WenDetailcellHeadView
        
        contentView.addSubview(headView)
        contentView.addSubview(titleLabel)
        contentView.addSubview(tableView)
        
        //head
        headView.huifuButton.addTarget(self, action: #selector(WenWenDetailTableViewCellStyleTwo.buttonClicked(_:)), forControlEvents: .TouchUpInside)
        
        //titleLabel
        titleLabel.numberOfLines = 0
        titleLabel.textColor = UIColor.darkGrayColor()
        titleLabel.font = UIFont.systemFontOfSize(17)
        
        //tableView
        tableView.separatorStyle = .None
        tableView.tableFooterView = UIView()
        tableView.delegate = self
        tableView.dataSource = self
        tableView.userInteractionEnabled = false
        
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        if model == nil {
            return
        }
        headView.snp_makeConstraints { (make) in
            make.left.equalTo(self.snp_left)
            make.right.equalTo(self.snp_right)
            make.top.equalTo(self.snp_top)
            make.height.equalTo(70)
        }
        
        titleLabel.snp_makeConstraints { (make) in
            make.left.equalTo(self.snp_left).offset(8)
            make.right.equalTo(self.snp_right).offset(-8)
            make.top.equalTo(headView.snp_bottom)
            make.height.equalTo(ToolManager.calculateStringSize(model!.content, maxW: kScreen_W - 16, maxH: 1000, fontSize: 18).height)
        }
        
        tableView.snp_removeConstraints()
        tableView.snp_makeConstraints { (make) in
            make.left.equalTo(self.snp_left)
            make.right.equalTo(self.snp_right)
            make.top.equalTo(titleLabel.snp_bottom)
            var height:CGFloat = 4
            for item in cellHeightArray {
                height += item
            }
            //                print(height)
            make.height.equalTo(height)
        }
    }
}

//MARK: - 協(xié)議
extension WenWenDetailTableViewCellStyleTwo:UITableViewDelegate,UITableViewDataSource{
    
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if childArray == nil {
            return 0
        }
        return childArray!.count
    }
    
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        var cell = tableView.dequeueReusableCellWithIdentifier("cell")
        if cell == nil {
            cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "cell")
        }
        cell?.selectionStyle = .None
        if indexPath.row < childArray!.count {
            cell?.textLabel?.textColor = UIColor.darkGrayColor()
            let model = childArray![indexPath.row] as! childModel
//            print("模型:\(model)")
            let str1 = ToolManager.stringByX(model.mobile_phone, startindex: 3, endindex: 7)
            let str2 = ToolManager.stringByX(model.tomobile_phone, startindex: 3, endindex: 7)
            let attr1 = NSMutableAttributedString(string: "\(str1)回復(fù)\(str2):\(model.content)")
            let attr2 = ToolManager.mixTextColor(attr1, from: 0, to: 11, color: userNameColor) as! NSMutableAttributedString
//            print("字符串:\(attr1)")
            cell?.textLabel?.attributedText = ToolManager.mixTextColor(attr2, from: 13, to: 11, color: userNameColor)
            cell?.textLabel?.numberOfLines = 0
        }
        return cell!
    }
    
    func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        if indexPath.row < cellHeightArray.count {
            return cellHeightArray[indexPath.row]
        }
        return 0
    }
}

//MARK: - 計(jì)算外層(即本身)cell高度
extension WenWenDetailTableViewCellStyleTwo{
    
    func getCellHeightArray(array:NSMutableArray) -> [CGFloat]{
        var cellHArray = [CGFloat]()
        
        for item in array {
            let model = item as! WenWenCellStyleTwoMode
            let h1 = ToolManager.calculateStringSize(model.content, maxW: kScreen_W - 16, maxH: 1000, fontSize: 18).height
            let array2 = model.child
            if array2?.count > 0 {
                var h2:CGFloat = 0
                for comen in array2! {
                    let model2 = comen as! childModel
                    h2 += ToolManager.calculateStringSize("\(model2.mobile_phone)回復(fù)\(model2.tomobile_phone):\(model2.content)", maxW: kScreen_W - 16, maxH: 10000, fontSize: 17).height + 10
                }
                cellHArray.append(h1 + h2 + 84*kScrennScale + 5)
            }else{
                cellHArray.append(h1 + 75)
            }
        }
        return cellHArray
    }
}

//MARK:按鈕點(diǎn)擊
extension WenWenDetailTableViewCellStyleTwo{
    
    func buttonClicked(sender:UIButton){
        print("回復(fù)層主")
        self.delegate?.huifuButtonClicked(model!.user_id, answer_id: model!.id)
    }
}

在最外層tableView中相關(guān)方法

import UIKit
import Alamofire

class WenWenDetailViewController: BasicViewController {
    
    //上一個(gè)界面?zhèn)鬟f問題id
    var questionID = ""
    // 數(shù)據(jù)源
    var cellOneModel:WenWenCellStyleOneMode? = nil//第一組
    //第二組
    lazy var dataArray: NSMutableArray = {
       return NSMutableArray()
    }()
    
    //cell高度
    var cellOneHeight:CGFloat = 0 //第一組
    //第二組
    var cellHeightArray = [CGFloat]()
    
    //屬性
    var tableView = UITableView()
    let huifuView = UIView()
    let textView = UITextView()
    
    /// 判斷是回復(fù)還是回答 1:回答 2:回復(fù) 默認(rèn)1
    var type = 1
    
    //存儲回復(fù)層主的id
    var touser_id = ""
    var answer_id = ""
    
    //MARK: 生命周期
    override func viewDidLoad() {
        super.viewDidLoad()
        creatUI()
        navigationSetting()
        getNetData()
        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(WenWenDetailViewController.keyboardWillAppear(_:)), name:UIKeyboardWillShowNotification, object:nil)
    }
    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        self.navigationController?.navigationBar.translucent = false
    }
    
    override func viewWillDisappear(animated: Bool) {
        super.viewWillDisappear(animated)
        self.navigationController?.navigationBar.translucent = true
        self.clearAllNotice()
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
    
    deinit{
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }
}

//MARK: 界面相關(guān)
extension WenWenDetailViewController{
    override func creatUI() {
        self.automaticallyAdjustsScrollViewInsets = false
        view.backgroundColor = APSGrayColor
        
        //tableView
        tableView.frame = CGRectMake(0, 0, kScreen_W, kScreen_H - 64 - 70*kScrennScale)
        view.addSubview(tableView)
        tableView.tableFooterView = UIView()
        tableView.delegate = self
        tableView.dataSource = self
        
        //回復(fù)框
        huifuView.frame = CGRectMake(0,kScreen_H - 64 - 70,kScreen_W,70*kScrennScale)
        huifuView.backgroundColor = APSGrayColor
        view.addSubview(huifuView)
        textView.frame = CGRectMake(30, 10*kScrennScale, kScreen_W - 150, 40*kScrennScale)
        textView.layer.masksToBounds = true
        textView.layer.cornerRadius = 3
        textView.delegate = self
        textView.returnKeyType = .Done
        textView.font = UIFont.systemFontOfSize(17)
        huifuView.addSubview(textView)
        let huifuButton = UIButton(frame: CGRectMake(textView.frame.origin.x+textView.frame.width+10,10*kScrennScale,kScreen_W-60-10-textView.frame.width,40*kScrennScale))
        huifuView.addSubview(huifuButton)
        huifuButton.setTitle("回復(fù)", forState: .Normal)
        huifuButton.backgroundColor = APSOrangeColor
        huifuButton.layer.masksToBounds = true
        huifuButton.layer.cornerRadius = 3
        huifuButton.addTarget(self, action: #selector(WenWenDetailViewController.buttonClicked(_:)), forControlEvents: .TouchUpInside)
        
        //注冊cell
        tableView.registerClass(WenWenDetailTableViewCellStyleOne.self, forCellReuseIdentifier: "cellOne")
        tableView.registerClass(WenWenDetailTableViewCellStyleTwo.self, forCellReuseIdentifier: "cellTwo")
        
    }
    override func navigationSetting() {
        self.navigationItem.title = "問題詳情"
        self.navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName:UIColor.blackColor()]
    }
}

//MARK: - tableView協(xié)議
extension WenWenDetailViewController: UITableViewDelegate,UITableViewDataSource{
    
    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 2
    }
    
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if section == 0 {
            return 1
        }
        return dataArray.count
    }
    
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        //第一組
        if indexPath.section == 0{
            let cell = tableView.dequeueReusableCellWithIdentifier("cellOne", forIndexPath: indexPath) as! WenWenDetailTableViewCellStyleOne
            cell.selectionStyle = .None
            cell.model = nil
            if cellOneModel != nil {
                cell.model = cellOneModel
            }
            return cell
        }
        
        //第二組
        let cell = tableView.dequeueReusableCellWithIdentifier("cellTwo", forIndexPath: indexPath) as! WenWenDetailTableViewCellStyleTwo
        cell.selectionStyle = .None
        cell.model = nil
        if indexPath.row < dataArray.count {
            let model = dataArray[indexPath.row] as! WenWenCellStyleTwoMode
            cell.model = nil
            cell.model = model
            cell.delegate = self
        }
        return cell
    }
    
    func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        if indexPath.section == 0 {
            return cellOneHeight
        }
        //第二組
        if indexPath.row < cellHeightArray.count {
            return cellHeightArray[indexPath.row]
        }
        return 0
    }
    
    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        
    }
}

//MARK: - 網(wǎng)絡(luò)請求
extension WenWenDetailViewController{
    
    func getNetData(){
        pleaseWait()
        Alamofire.request(.GET, getComentsListURL, parameters: ["id":questionID,"user_id":crrentUser!.user_id], encoding: .URL, headers: nil).responseJSON(options: NSJSONReadingOptions.MutableContainers) { (result) in
            self.clearAllNotice()
            if let json = result.result.value{
                let code = json.objectForKey("code")?.stringValue
                if code == "200"{
                    if let data = json.objectForKey("data") as? NSDictionary{
                        self.cellOneModel = WenWenCellStyleOneMode.yy_modelWithDictionary(data as [NSObject : AnyObject])
                        if self.cellOneModel != nil{
                            self.cellOneHeight = WenWenDetailTableViewCellStyleOne().getCellHeight(self.cellOneModel!)
                        }
                        
                        //第二組
                        let child = data["child"]
                        let modelArray = NSArray.yy_modelArrayWithClass(WenWenCellStyleTwoMode.self, json: child!)
                        self.dataArray.removeAllObjects()
                        self.dataArray.addObjectsFromArray(modelArray!)
                        self.cellHeightArray.removeAll()
                        self.cellHeightArray = WenWenDetailTableViewCellStyleTwo().getCellHeightArray(self.dataArray)
                        
                        self.tableView.reloadData()
                    }//data結(jié)束
                }//code結(jié)束
            }//json結(jié)束
        }//Alamofire結(jié)束
    }//函數(shù)結(jié)束
}

//MARK: textViewDelegate
extension WenWenDetailViewController:UITextViewDelegate{
    
    func keyboardWillAppear(notification:NSNotification) {
    
    let userInfo = notification.userInfo![UIKeyboardFrameEndUserInfoKey]
    
    let keyboardY = userInfo!.CGRectValue.size.height

        UIView.animateWithDuration(1) {
            self.huifuView.frame = CGRectMake(0,kScreen_H - 64 - 70 - keyboardY,kScreen_W,70*kScrennScale)
        }
    }
    
    func textViewDidBeginEditing(textView: UITextView) {
        
    }
    
    func textViewDidEndEditing(textView: UITextView) {
        UIView.animateWithDuration(0.2) {
            self.huifuView.frame = CGRectMake(0,kScreen_H - 64 - 70,kScreen_W,70*kScrennScale)
        }
    }
    
    func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
        if text.containsString("\n") {
            self.view.endEditing(true)
            return false
        }
        return true
    }
}

//MARK:按鈕點(diǎn)擊事件
extension WenWenDetailViewController:WenCellStyleTwoDelegate{
    
    func buttonClicked(sender:UIButton){
        sender.userInteractionEnabled = false
        print("回復(fù)")
        textView.resignFirstResponder()
        
        //提交
        if textView.text.characters.count == 0 {
            noticeOnlyText("回復(fù)內(nèi)容不能為空", autoClear: true, autoClearTime: 1)
            sender.userInteractionEnabled = true
            return
        }
        
        //回答
        var url = answerURL
        var parameters = ["user_id":crrentUser!.user_id,"id":cellOneModel!.id,"content":textView.text!]
        
        if type == 2 {
            //回復(fù)
            url = huifuURL
            parameters = ["user_id":crrentUser!.user_id,"touser_id":touser_id,"id":cellOneModel!.id,"answer_id":answer_id,"content":textView.text!]
        }
//        print(url)
//        print(parameters)
        Alamofire.request(.GET, url, parameters: parameters, encoding: .URL, headers: nil).responseJSON(options: NSJSONReadingOptions.MutableContainers) { (result) in
            self.type = 1
            sender.userInteractionEnabled = true
            if let json = result.result.value{
                let code = json.objectForKey("code")?.stringValue
//                print(code)
                if code == "200"{
                    self.textView.text = nil
                    self.noticeOnlyText("評論成功", autoClear: true, autoClearTime: 1)
                    self.performSelector(#selector(WenWenDetailViewController.getNetData), withObject: nil, afterDelay: 1)
                }else{
                    self.noticeOnlyText("參數(shù)錯誤", autoClear: true, autoClearTime: 1)
                }
            }else{
                self.noticeOnlyText("服務(wù)器開小差啦", autoClear: true, autoClearTime: 1)
            }
        }
    }
    
    func huifuButtonClicked(touser_id:String,answer_id:String){
        //回復(fù)層主
        textView.becomeFirstResponder()
        textView.text = nil
        self.type = 2
        self.answer_id = answer_id
        self.touser_id = touser_id
    }
    
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容