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:%@",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,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,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))
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,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,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!
}