swift中UITableView的使用(cell复用-自适应高度、headerView复用、footerView复用)

https://github.com/potato512/SYSwiftLearning

效果图



// MARK: - 数据
func setLocalData()
{
        self.mainArray = NSMutableArray()
        
        for number in 1...3
        {
            let rowArray:NSMutableArray = NSMutableArray()
            for numberTmp in 1...2
            {
                let model = CustomModel()
                model.title = "方法/步骤"
                model.content = "比如,我有一个ELCImagePickerController类,需要增加一个tag属性,代码如下:软件基本信息。使用TableViewController自定义列表。版权声明:本文为博主原创文章,未经博主允许不得转载。swift自定义UITableViewCell,并配置到UITableView的注意事项"
                model.contentStatus = ((numberTmp % 2 == 0) ? true : false)
                
                rowArray.addObject(model)
            }
            
            let dict:NSMutableDictionary = NSMutableDictionary()
            // cell值
            dict.setObject(rowArray, forKey: "rowCell")
            // 页眉,页脚标题
            let numberTmp = random() % 1000 + number
            dict.setObject(String(format: "headerTitle:%@", arguments: [String(numberTmp)]), forKey: "rowHeader")
            dict.setObject(String(format: "footerTitle:%@", arguments: [String(numberTmp)]), forKey: "rowFooter")
            // cell展开,或收起来状态
            dict.setObject(((number % 2 == 0) ? true : false), forKey: "rowStatus")
            
            self.mainArray.addObject(dict)
        }
}
// MARK: - 视图
func setUI()
{
        // 列表样式分plain,grouped,其中grouped在列表有页眉,页脚时会随cell滚动,而plain则是先固定后滚动
        self.mainTableView = UITableView(frame: self.view.bounds, style: UITableViewStyle.Grouped)
        self.view.addSubview(self.mainTableView)
        self.mainTableView.backgroundColor = UIColor.clearColor()
        self.mainTableView.delegate = self
        self.mainTableView.dataSource = self
        self.mainTableView.autoresizingMask = UIViewAutoresizing.FlexibleHeight
        self.mainTableView.tableFooterView = UIView()
        
        // 创建一个重用的页眉
        self.mainTableView!.registerClass(CustomHeader.self, forHeaderFooterViewReuseIdentifier: CustomHeaderIdentifier)
        // 创建一个重用的页脚
        self.mainTableView!.registerClass(CustomFooter.self, forHeaderFooterViewReuseIdentifier: CustomFooterIdentifier)
        // 创建一个重用的单元格
        self.mainTableView!.registerClass(CustomCell.self, forCellReuseIdentifier: CustomCellIdentifier)
}
// MARK: - UITableViewDataSource, UITableViewDelegate
    
// 分组
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return self.mainArray.count
}
    
// MARK: 页眉视图
func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return CustomHeaderHeight
}
    
//    func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
//
//        let dict:NSDictionary! = self.mainArray[section] as! NSDictionary
//        let title:String! = dict.objectForKey("rowHeader") as! String
//
//        return title
//    }
    
// 自定义页眉(注意:自定义时,高度与代理方法中的高度一致,同时代理方法中的标题失效)
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        
        // 自定义视图,未复用
        /*
        let view = UIButton(frame: CGRectMake(0.0, 0.0, CGRectGetWidth(self.mainTableView.frame), 40.0))
        view.backgroundColor = UIColor.greenColor()
        view.contentHorizontalAlignment = .Center
        view.setTitleColor(UIColor.blackColor(), forState: .Normal)
        view.setTitleColor(UIColor.redColor(), forState: .Highlighted)
        
        // 响应事件,用于修改cell显示状态,即打开,或收起来
        view.tag = section
        view.addTarget(self, action: Selector("statusClick:"), forControlEvents: .TouchUpInside)
        
        let dict:NSDictionary! = self.mainArray[section] as! NSDictionary
        let title:String! = dict.objectForKey("rowHeader") as! String
        view.setTitle(title, forState: .Normal)

        return view
        */

        
        // 自定义视图,重用方法
        let headerView = CustomHeader(reuseIdentifier: CustomHeaderIdentifier)
        // 响应事件,用于修改cell显示状态,即打开,或收起来
        headerView.headerButton.tag = section
        headerView.headerButton.addTarget(self, action: Selector("statusClick:"), forControlEvents: .TouchUpInside)
        // 标题
        let dict:NSDictionary! = self.mainArray[section] as! NSDictionary
        let title:String! = dict.objectForKey("rowHeader") as! String
        headerView.headerButton.setTitle(title, forState: .Normal)

        return headerView
}
    
// MARK: 页脚视图
func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
        return CustomFooterHeight
}
    
//    func tableView(tableView: UITableView, titleForFooterInSection section: Int) -> String? {
//
//        let dict:NSDictionary! = self.mainArray[section] as! NSDictionary
//        let title:String! = dict.objectForKey("rowFooter") as! String
//
//        return title
//    }
    
// 自定义页脚(注意:自定义时,高度与代理方法中的高度一致,同时代理方法中的标题失效)
func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
        
        // 自定义页脚视图,未重用
        /*
        let view = UILabel(frame: CGRectMake(0.0, 0.0, CGRectGetWidth(self.mainTableView.frame), 40.0))
        view.backgroundColor = UIColor.yellowColor()
        view.textAlignment = .Center
        
        let dict:NSDictionary! = self.mainArray[section] as! NSDictionary
        let title:String! = dict.objectForKey("rowFooter") as! String
        view.text = title
        
        return view
        */
        
        // 自定义可重用页脚视图
        let footerView = CustomFooter(reuseIdentifier: CustomFooterIdentifier)
        let dict:NSDictionary! = self.mainArray[section] as! NSDictionary
        let title:String! = dict.objectForKey("rowFooter") as! String
        footerView.label.text = title
        
        return footerView
}
    
// MARK: cell单元格
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        
        let dict:NSDictionary! = self.mainArray[section] as! NSDictionary
        let status:Bool! = dict.objectForKey("rowStatus") as! Bool
        if status.boolValue
        {
            let array:NSArray! = dict.objectForKey("rowCell") as! NSArray
            return array.count
        }
        
        return 0
}
    
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
      
        let dict:NSDictionary! = self.mainArray[indexPath.section] as! NSDictionary
        let array:NSArray! = dict.objectForKey("rowCell") as! NSArray
        let data:CustomModel! = array[indexPath.row] as! CustomModel
        let height = CustomCell.cellHeight(data)
        
        return height
}
    
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        
        let dict:NSDictionary! = self.mainArray[indexPath.section] as! NSDictionary
        let array:NSArray! = dict.objectForKey("rowCell") as! NSArray
        let data:CustomModel! = array[indexPath.row] as! CustomModel
        let cell = CustomCell(model:data, cellIndex: indexPath, reuseIdentifier: CustomCellIdentifier)
        cell.contentButton.addTarget(self, action: Selector("buttonClick:"), forControlEvents: .TouchUpInside)
        
        return cell
}
    
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
// MARK: - click
    
// statusClick
func statusClick(button:UIButton)
{
        let section = button.tag
        
        let dict:NSMutableDictionary! = self.mainArray[section] as! NSMutableDictionary
        let status:Bool! = dict.objectForKey("rowStatus") as! Bool
        dict.setObject((status.boolValue ? false : true), forKey: "rowStatus")
        
        self.mainArray.replaceObjectAtIndex(section, withObject: dict)
        
        self.mainTableView.reloadSections(NSIndexSet(index: section), withRowAnimation: .None)
}
    
// buttonClick
func buttonClick(button:UIButton)
{
        button.selected = !button.selected
        
        let indexPath = button.indexPath
        print("当前点击的按钮是:\(indexPath.section) + \(indexPath.row)")
        
        let dict:NSDictionary! = self.mainArray[indexPath.section] as! NSDictionary
        let array:NSArray! = dict.objectForKey("rowCell") as! NSArray
        let data:CustomModel! = array[indexPath.row] as! CustomModel
        let status:Bool! = data.contentStatus as Bool
        if status.boolValue
        {
            data.contentStatus = false
        }
        else
        {
            data.contentStatus = true
        }
        // 刷新数据,只刷新修改数据的信息
        self.mainTableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .None)
        // 刷新数据,刷新全部信息
//        self.mainTableView.reloadData()
}

自定义cell

import UIKit


// cell复用标识
let CustomCellIdentifier = "CustomCell"

let width:CGFloat = UIScreen.mainScreen().bounds.width
let contentFont:CGFloat = 12.0

// 默认高度
let originXY = 10.0
let labelHeight = 30.0
let CustomCellHeightDefault = CGFloat(originXY + labelHeight + originXY + originXY + 0.0)

class CustomCell: UITableViewCell {

    // 标题标签
    private var titleLabel:UILabel!
    // 详情按钮
    var contentButton:UIButton!
    // 显示或隐藏图标
    private var statusImage:UIImageView!
    // 副标题标签
    private var contentLabel:UILabel!
    
    // 消息数据结构
    var cellModel:CustomModel!
    private var cellIndex:NSIndexPath!
    
    
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

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

        // Configure the view for the selected state
    }
    
    
    // MARK: - 实例化方法
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
    
    
    // 实例化cell
    init(model data:CustomModel, cellIndex index:NSIndexPath, reuseIdentifier cellId:String)
    {
        super.init(style: UITableViewCellStyle.Default, reuseIdentifier:cellId)
        // cell属性设置
//        self.selectionStyle = UITableViewCellSelectionStyle.None
        self.backgroundColor = UIColor.whiteColor()
        
        self.cellModel = data
        self.cellIndex = index
        self.setUI()
        self.showModel()
    }
    
    // 让单元格宽度始终为屏幕宽
    override var frame: CGRect
    {
        get
        {
            return super.frame
        }
        set (newFrame)
        {
            var frame = newFrame
            frame.size.width = width
            super.frame = frame
        }
    }
    
    // MARK: 视图
    
    func setUI()
    {
        // 10.0 + 40.0 + 10.0 + 10.0 + 自适应?(40.0)
        
        // 实例化
        if (self.titleLabel == nil)
        {
            self.titleLabel = UILabel(frame: CGRectZero)
            self.contentView.addSubview(self.titleLabel)
            
            self.titleLabel.textColor = UIColor.blackColor()
            self.titleLabel.font = UIFont.systemFontOfSize(14.0)
        }
        
        if (self.contentButton == nil)
        {
            self.contentButton = UIButton(type: .Custom)
            self.contentView.addSubview(self.contentButton)
            
            self.contentButton.backgroundColor = UIColor.orangeColor()
            self.contentButton.layer.cornerRadius = 5.0
            self.contentButton.layer.masksToBounds = true
            self.contentButton.titleLabel!.font = UIFont.systemFontOfSize(12.0)
            self.contentButton.setTitleColor(UIColor.redColor(), forState: .Highlighted)
        }
     
        if (self.statusImage == nil)
        {
            self.statusImage = UIImageView(frame: CGRectZero)
            self.contentView.addSubview(self.statusImage)
            
            self.statusImage.contentMode = .ScaleAspectFit
        }
        
        if (self.contentLabel == nil)
        {
            self.contentLabel = UILabel(frame: CGRectZero)
            self.contentView.addSubview(self.contentLabel)
            
            self.contentLabel.textColor = UIColor.brownColor()
            self.contentLabel.font = UIFont.systemFontOfSize(contentFont)
            self.contentLabel.numberOfLines = 0
            self.contentLabel.lineBreakMode = NSLineBreakMode.ByWordWrapping
        }
        
        
        // 设置frame
        // 标题
        self.titleLabel.frame = CGRectMake(CGFloat(originXY), CGFloat(originXY), (CGRectGetWidth(self.frame) - CGFloat(originXY) * 3 - 60.0), CGFloat(labelHeight))
        var currentView = self.titleLabel as UIView
        // 按钮
        self.contentButton.frame = CGRectMake((CGRectGetWidth(self.frame) - CGFloat(originXY) - 60.0), CGRectGetMinY(currentView.frame), 60.0, CGRectGetHeight(currentView.frame))
        // 分割线
        let lineH = UIView(frame: CGRectMake(CGFloat(originXY), (CGRectGetMinY(currentView.frame) + CGRectGetHeight(currentView.frame) + CGFloat(originXY) - 0.5), (CGRectGetWidth(self.frame) - CGFloat(originXY) * 2), 0.5))
        self.contentView.addSubview(lineH)
        lineH.backgroundColor = UIColor.lightGrayColor()
        // 状态图标
        self.statusImage.frame = CGRectMake(CGRectGetMinX(currentView.frame), (CGRectGetMinY(currentView.frame) + CGRectGetHeight(currentView.frame) + CGFloat(originXY)), CGFloat(originXY), CGFloat(originXY))
        currentView = self.statusImage as UIView
        // 详情
        self.contentLabel.frame = CGRectMake(CGFloat(originXY), (CGRectGetMinY(currentView.frame) + CGRectGetHeight(currentView.frame)), (width - CGFloat(originXY) * 2), 0.0)
    }
    
    // MARK: 数据处理
    func showModel()
    {
        self.titleLabel.text = self.cellModel.title
        self.contentLabel.text = self.cellModel.content
        self.contentButton.indexPath = self.cellIndex
        
        let status = self.cellModel.contentStatus
        if status.boolValue
        {
            self.contentButton.setTitle("隐藏详情", forState: .Normal)
            self.contentButton.setTitleColor(UIColor.blueColor(), forState: .Normal)
            
            self.statusImage.image = UIImage(named: "statusDown_image")
            
            // 计算字生符串的宽度,高度
            var rect = self.contentLabel.frame
            let height = CustomCell.heightWithText(self.cellModel.content)
            rect.size.height = height
            self.contentLabel.frame = rect
        }
        else
        {
            self.contentButton.setTitle("显示详情", forState: .Normal)
            self.contentButton.setTitleColor(UIColor.blackColor(), forState: .Normal)
            
            self.statusImage.image = UIImage(named: "statusUp_image")
            
            // 隐藏
            var rect = self.contentLabel.frame
            rect.size.height = 0.0
            self.contentLabel.frame = rect
        }
    }
    
    // MARK: - 计算高度
    class func cellHeight(model:CustomModel) -> CGFloat
    {
        let status = model.contentStatus
        if status.boolValue
        {
            let height = self.heightWithText(model.content)
            return CustomCellHeightDefault + height
        }
        else
        {
            return CustomCellHeightDefault
        }
    }
    
    private class func heightWithText(text:String) -> CGFloat
    {
        let size:CGRect = text.boundingRectWithSize(CGSizeMake(width, 999.9), options: NSStringDrawingOptions.UsesLineFragmentOrigin, attributes: [NSFontAttributeName:UIFont.systemFontOfSize(contentFont)], context: nil)
        
        return size.height
    }
}

自定义headerView

import UIKit

let CustomHeaderHeight:CGFloat = 40.0
let CustomHeaderIdentifier = "CustomHeader"
let CustomHeaderWidth:CGFloat = UIScreen.mainScreen().bounds.width

class CustomHeader: UITableViewHeaderFooterView {

    // 标题按钮
    var headerButton:UIButton!
    
    
    // 必须实现的方法
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    // 实例化
    override init(reuseIdentifier: String?)
    {
        super.init(reuseIdentifier: reuseIdentifier)
        
        self.setUI()
    }
    
    // 让单元格宽度始终为屏幕宽
    override var frame: CGRect
    {
        get
        {
            return super.frame
        }
        set (newFrame)
        {
            var frame = newFrame
            frame.size.width = CustomHeaderWidth
            super.frame = frame
        }
    }

    
    
    // 视图
    private func setUI()
    {
        if self.headerButton == nil
        {
            self.headerButton = UIButton(frame: CGRectMake(0.0, 0.0, CustomHeaderWidth, CustomHeaderHeight))
            self.contentView.addSubview(self.headerButton)
            
            self.headerButton.backgroundColor = UIColor.greenColor()
            self.headerButton.contentHorizontalAlignment = .Center
            self.headerButton.setTitleColor(UIColor.blackColor(), forState: .Normal)
            self.headerButton.setTitleColor(UIColor.redColor(), forState: .Highlighted)
        }
    }

}

自定义footerView

import UIKit

let CustomFooterHeight:CGFloat = 40.0
let CustomFooterIdentifier = "CustomFooter"
let CustomFooterWidth:CGFloat = UIScreen.mainScreen().bounds.width

class CustomFooter: UITableViewHeaderFooterView {

    var label:UILabel!
    
    // 必须实现
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    // 实例化
    override init(reuseIdentifier: String?)
    {
        super.init(reuseIdentifier: reuseIdentifier)
        
        self.setUI()
    }

    
    
    // 视图
    private func setUI()
    {
        if self.label == nil
        {
            self.label = UILabel(frame: CGRectMake(0.0, 0.0, CustomFooterWidth, CustomFooterHeight))
            self.contentView.addSubview(self.label)
            
            self.label.font = UIFont.systemFontOfSize(10.0)
            self.label.textAlignment = .Center
            self.label.backgroundColor = UIColor.yellowColor()
        }
    }
}

自定义model

import UIKit

class CustomModel: NSObject {

    // 标题
    var title:String!
    // 内容
    var content:String!
    // 内容显示,或隐藏状态
    var contentStatus:Bool!
}


猜你喜欢

转载自blog.csdn.net/potato512/article/details/52911957