Swift创建一个选择题库界面(解决TableViewCell中Button的selected状态混乱和手势事件被截拦问题)-1
Swift创建一个选择题库界面(解决TableViewCell中Button的selected状态混乱和手势事件被截拦问题)-2
Swift创建一个选择题库界面(解决TableViewCell中Button的selected状态混乱和手势事件被截拦问题)-3
第三步:创建UITableViewCell,名为XXWDCell.swift
将storyboard中的控件关联到XXWDCell.swift中,storyboard中Cell的CustomClass关联到XXWDCell
所有的选项button和label都分别按顺序关联到optionsBtn和optionsLabel这个IBOutlet中,并将所有的选项button都关联到selectAnswerAction这个IBAction中
@IBOutlet weak var backView: UIView!//背景
@IBOutlet var optionsLabel: [UILabel]!//选项labels
@IBOutlet weak var titleLabel: UILabel!//题干
@IBOutlet var optionsBtn: [UIButton]!//选项buttons
@IBAction func selectAnswerAction(sender: UIButton) {
}```
然后在drawRect中给backView设置圆角
override func drawRect(rect: CGRect) {
backView.layer.cornerRadius = 10
backView.layer.masksToBounds = true
}```
然后定一个变量model,在写model时,配置cell
var model:Exercise? {
didSet {
self.titleLabel.text = model!.title!
for i in 0..<4 {
self.optionsLabel[i].text = model?.options![i] as? String
}
}
}```
**第四步:创建TableViewController,名为XXWDViewController.swift**
在ViewdidLoad中初始化一些设置
//Mark: - View生命周期事件
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.navigationBar.tintColor = UIColor.whiteColor()
self.navigationController?.navigationBar.barTintColor = UIColor(red:227/255, green: 23/255, blue: 13/255, alpha: 1)
self.tableView.delaysContentTouches = false
self.tableView.allowsSelection = false
self.tableView.tableFooterView = UIView()
}```
首先需要解析plist文件,定义一个lazy属性dataArray为NSDictionary,因为plist的根项目为Dictionary,并定义一个全局变量xxwdcell,如下:
var xxwdcell:XXWDCell!
//Mark: - 懒加载
lazy var dataArray:NSDictionary = {
let path = NSBundle.mainBundle().pathForResource("testLibraryList.plist", ofType: nil)
return NSDictionary(contentsOfFile: path!)!
}()```
然后把单选的题目和多选的题目分别读取到singleChoiceArray和multipleChoiceArray中,因为本项目用到了两个section
lazy var singleChoiceArray:NSArray = {
return self.dataArray["单选"]! as! NSArray
}()```
lazy var multipleChoiceArray:NSArray = {
return self.dataArray["多选"]! as! NSArray
}()```
**配置TableViewDataSource**
// Mark: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return self.dataArray.count
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
return self.singleChoiceArray.count
}
if section == 1 {
return self.multipleChoiceArray.count
}
return 0
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
xxwdcell = tableView.dequeueReusableCellWithIdentifier("XXWDCell") as! XXWDCell
return xxwdcell
}```
配置TableViewDelegate
在willDisplayCell这个方法中完成了以下几件事情:
- 1.增加题型和序号,这些其实可以在plist文件里面做,在这里可以偷懒,直接程序给你搞定,不过这样更消耗资源,建议不这么做;
- 2.给optionsBtn设置了tag,如果不每个optionsBtn都设置tag的话,将相应不了button的点击事件,还有方便以后button状态混乱的处理(混乱:你在第一个cell中选中了A选项,你会发现在后面的第4、8个cell中均选中了A选项,但是第4、8个cell并没有响应button点击事件)
- 3.给xxwdcell的model赋值
之所以在willDisplayCell做这些事情而不是放到cellForRowAtIndexPath中是因为在将呈现cell之前就把相应的事情处理了,会更流畅
//Mark: - UITableViewDelegate
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
if indexPath.section == 0 {
//增加题型和序号,这些其实可以在plist文件里面做
dict.setDictionary(self.singleChoiceArray[indexPath.row] as! [NSObject : AnyObject])
dict.setObject("单选", forKey: "type")
dict.setObject(indexPath.row, forKey: "index")
//设置选择按钮的tag,防止复用时发生混乱
for i in 0..<4 {
xxwdcell.optionsBtn[i].tag = 100 + indexPath.row * 4 + i
}
}
if indexPath.section == 1 {
//增加题型和序号,这些其实可以在plist文件里面做
dict.setDictionary(self.multipleChoiceArray[indexPath.row] as! [NSObject : AnyObject])
dict.setObject("多选", forKey: "type")
dict.setObject(indexPath.row, forKey: "index")
//设置选择按钮的tag,防止复用时发生混乱
for i in 0..<4 {
xxwdcell.optionsBtn[i].tag = 1000 + indexPath.row * 4 + i
}
}
xxwdcell.model = Exercie(dict: dict)
}```
设置section头的高度
override func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 10
}```
要实现自适应布局就要计算每一个cell的高度,思路如下:
总高度=题目高度+每个选项label的高度+每个label的上下边距,每个选项label的高度需要通过contentsizeForLabel方法来计算,三个参数size为label的(宽度和最大高度),注意宽度要减去label的左右边距,content为label的内容,还有font为字体大小
heightForRowAtIndexPath方法中就是按照去内容-计算各个label高度-计算总高度这样的顺序计算的
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if indexPath.section == 0 {
//增加题型和序号,这些其实可以在plist文件里面做
dict.setDictionary(self.singleChoiceArray[indexPath.row] as! [NSObject : AnyObject])
dict.setObject("单选", forKey: "type")
dict.setObject(indexPath.row, forKey: "index")
}
if indexPath.section == 1 {
//增加题型和序号,这些其实可以在plist文件里面做
dict.setDictionary(self.multipleChoiceArray[indexPath.row] as! [NSObject : AnyObject])
dict.setObject("多选", forKey: "type")
dict.setObject(self.singleChoiceArray.count + indexPath.row, forKey: "index")
}
let md:Exercie = Exercie(dict: dict)
md.title = "\(indexPath.row + 1)." + "\(md.title!)" + "(\(md.type))"//在标题中增加序号和题型,用来计算准确
//计算label的总高度
var height = self.contentsizeForLabel(CGSizeMake(screen_width - 26, CGFloat(MAXFLOAT)), content: md.title, font: UIFont.systemFontOfSize(17)).height//减去边界才能计算准确
for str in md.options! {
height = height + contentsizeForLabel(CGSizeMake(screen_width - 56,CGFloat(MAXFLOAT)),content:str as! NSString,font:UIFont.boldSystemFontOfSize(17)).height + 10//减去边界才能计算准确
}
return height + 30
}
//计算Label高度
private func contentsizeForLabel(size:CGSize,content:NSString,font:UIFont) -> CGSize{
let options : NSStringDrawingOptions = NSStringDrawingOptions.UsesLineFragmentOrigin
let size = content.boundingRectWithSize(size, options: options, attributes: [NSFontAttributeName:font], context: nil).size
return size
}```
在heightForRowAtIndexPath和willDisplayCell方法中,重复了增加题型和序号的工作和创建model的工作,其实因为heightForRowAtIndexPath方法在willDisplayCell方法之前执行,在heightForRowAtIndexPath创建一个全局变量exercise:Exercise,然后再在willDisplayCell调用就可以了。更改过后看起来就是这样的
var exercise:Exercise!
//Mark: - UITableViewDelegate
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
if indexPath.section == 0 {
//设置选择按钮的tag,防止复用时发生混乱
for i in 0..<4 {
xxwdcell.optionsBtn[i].tag = 100 + indexPath.row * 4 + i
}
}
if indexPath.section == 1 {
//设置选择按钮的tag,防止复用时发生混乱
for i in 0..<4 {
xxwdcell.optionsBtn[i].tag = 1000 + indexPath.row * 4 + i
}
}
xxwdcell.model = exercise
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if indexPath.section == 0 {
//增加题型和序号,这些其实可以在plist文件里面做
dict.setDictionary(self.singleChoiceArray[indexPath.row] as! [NSObject : AnyObject])
dict.setObject("单选", forKey: "type")
dict.setObject(indexPath.row, forKey: "index")
}
if indexPath.section == 1 {
//增加题型和序号,这些其实可以在plist文件里面做
dict.setDictionary(self.multipleChoiceArray[indexPath.row] as! [NSObject : AnyObject])
dict.setObject("多选", forKey: "type")
dict.setObject(self.singleChoiceArray.count + indexPath.row, forKey: "index")
}
exercise = Exercise(dict: dict)
exercise = "(indexPath.row + 1)." + "(exercise.title!)" + "((exercise.type))"//在标题中增加序号和题型,用来计算准确
//计算label的总高度
var height = self.contentsizeForLabel(CGSizeMake(screen_width - 26, CGFloat(MAXFLOAT)), content: exercise.title, font: UIFont.systemFontOfSize(17)).height//减去边界才能计算准确
for str in exercise.options! {
height = height + contentsizeForLabel(CGSizeMake(screen_width - 56,CGFloat(MAXFLOAT)),content:str as! NSString,font:UIFont.boldSystemFontOfSize(17)).height + 10//减去边界才能计算准确
}
return height + 30
}```
这样布局就告一段落,你可以运行一下,看下效果,或有什么错误
待续......
网友评论