TableViewCell嵌套TableView实现评论列表盖楼
2017-02-28 本文已影响310人
T92
效果
tableView的使用时需要细心去优化的,我这里就随便做了一下,界面目前没有卡顿现象。
如上图,我的界面是ViewController中加了一个TableView,tableView分了两组,第一组是显示的问题,第二组显示评论,现在实现的效果:直接点击最下面回复则回复楼主,点第二组cell上的回复层主,层主楼层中的回复不能再被评论。
思路:
由于评论条数,字数未知,所以最外层tableViewcell高度不固定,里层tableViewcell高度也不固定,就需要用Autolayout来布局,在这里选择用Snapkit做,在给里面的tableView布局时必须用 tableView.snp_removeConstraints()清空原来的约束,否则会冲突,当然也可以用更新约束的方法,自己尝试
嵌入的tableViewcell是系统自带的,最外层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高度数组
var cellHeightArray = [CGFloat]()
//数据源数组
var childArray:NSArray? = nil{
didSet{
if childArray == nil {
return
}
//计算本cell中tableView的cell高度
cellHeightArray.removeAll()
for item in childArray! {
let model = item as! childModel
let text = "\(model.mobile_phone)回复\(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: - 界面相关
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: - 协议
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)回复\(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: - 计算外层(即本身)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)回复\(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:按钮点击
extension WenWenDetailTableViewCellStyleTwo{
func buttonClicked(sender:UIButton){
print("回复层主")
self.delegate?.huifuButtonClicked(model!.user_id, answer_id: model!.id)
}
}
在最外层tableView中相关方法
import UIKit
import Alamofire
class WenWenDetailViewController: BasicViewController {
//上一个界面传递问题id
var questionID = ""
// 数据源
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()
/// 判断是回复还是回答 1:回答 2:回复 默认1
var type = 1
//存储回复层主的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: 界面相关
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
//回复框
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("回复", 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协议
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: - 网络请求
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结束
}//code结束
}//json结束
}//Alamofire结束
}//函数结束
}
//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:按钮点击事件
extension WenWenDetailViewController:WenCellStyleTwoDelegate{
func buttonClicked(sender:UIButton){
sender.userInteractionEnabled = false
print("回复")
textView.resignFirstResponder()
//提交
if textView.text.characters.count == 0 {
noticeOnlyText("回复内容不能为空", 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 {
//回复
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("参数错误", autoClear: true, autoClearTime: 1)
}
}else{
self.noticeOnlyText("服务器开小差啦", autoClear: true, autoClearTime: 1)
}
}
}
func huifuButtonClicked(touser_id:String,answer_id:String){
//回复层主
textView.becomeFirstResponder()
textView.text = nil
self.type = 2
self.answer_id = answer_id
self.touser_id = touser_id
}
}