效果
tableView的使用時(shí)需要細(xì)心去優(yōu)化的筷转,我這里就隨便做了一下蔚万,界面目前沒(méi)有卡頓現(xiàn)象零截。
如上圖涧衙,我的界面是ViewController中加了一個(gè)TableView弧哎,tableView分了兩組撤嫩,第一組是顯示的問(wèn)題序攘,第二組顯示評(píng)論两踏,現(xiàn)在實(shí)現(xiàn)的效果:直接點(diǎn)擊最下面回復(fù)則回復(fù)樓主赡麦,點(diǎn)第二組cell上的回復(fù)層主帕识,層主樓層中的回復(fù)不能再被評(píng)論肮疗。
思路:
由于評(píng)論條數(shù),字?jǐn)?shù)未知们衙,所以最外層tableViewcell高度不固定蒙挑,里層tableViewcell高度也不固定愚臀,就需要用Autolayout來(lái)布局姑裂,在這里選擇用Snapkit做欣鳖,在給里面的tableView布局時(shí)必須用 tableView.snp_removeConstraints()清空原來(lái)的約束观堂,否則會(huì)沖突师痕,當(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問(wèn)題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
//存儲(chǔ)回復(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)
//注冊(cè)cell
tableView.registerClass(WenWenDetailTableViewCellStyleOne.self, forCellReuseIdentifier: "cellOne")
tableView.registerClass(WenWenDetailTableViewCellStyleTwo.self, forCellReuseIdentifier: "cellTwo")
}
override func navigationSetting() {
self.navigationItem.title = "問(wèn)題詳情"
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ò)請(qǐng)求
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("評(píng)論成功", autoClear: true, autoClearTime: 1)
self.performSelector(#selector(WenWenDetailViewController.getNetData), withObject: nil, afterDelay: 1)
}else{
self.noticeOnlyText("參數(shù)錯(cuò)誤", autoClear: true, autoClearTime: 1)
}
}else{
self.noticeOnlyText("服務(wù)器開(kāi)小差啦", 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
}
}