美文网首页首页投稿(暂停使用,暂停投稿)程序员iOS Developer
Swift创建一个选择题库界面(解决TableViewCell中

Swift创建一个选择题库界面(解决TableViewCell中

作者: 9ad91f89b29e | 来源:发表于2016-07-31 12:01 被阅读903次

    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
    

    }```
    这样布局就告一段落,你可以运行一下,看下效果,或有什么错误
    待续......

    相关文章

      网友评论

        本文标题:Swift创建一个选择题库界面(解决TableViewCell中

        本文链接:https://www.haomeiwen.com/subject/mpitsttx.html