swift 文章收集iOS DeveloperiOS学习笔记

UITableView实现Accordion(手风琴)效果

2016-07-02  本文已影响597人  4074

Accordion(手风琴)效果在网页中十分常见。在屏幕更小,可显示范围更有限的移动端,更是使用频繁。

在 Web 开发中,使用 Javascript 操控 DOM,就可以轻松实现这种效果。

在 iOS 端呢,实现一个简易的 Accordion 效果,就简单程度而言,更是有过之而无不及。简直是一马平川、易如反掌,像过清晨的马路一样轻松。

OK,让我来演示一下。

Demo地址:https://github.com/4074/UITableViewAccordionDemo

storyboard操作

我们现在 storyboard 中创建一些必要的 view 和节点

屏幕快照 2016-07-02 下午8.13.47.png 屏幕快照 2016-07-02 下午8.18.02.png 屏幕快照 2016-07-02 下午8.20.49.png 屏幕快照 2016-07-02 下午8.21.13.png 屏幕快照 2016-07-02 下午8.37.16.png 屏幕快照 2016-07-02 下午8.22.01.png

编写代码

接下来主要就是编写代码的时间了。当然代码量十分有限。

class AccordionTableViewCell: UITableViewCell {

    @IBOutlet weak var wrapView: UIView!
    @IBOutlet weak var titleView: UIView!
    
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
        self.selectionStyle = .None
        
        wrapView.backgroundColor = UIColor.groupTableViewBackgroundColor()
        wrapView.layer.cornerRadius = 4
        wrapView.layer.masksToBounds = true
        
        titleView.backgroundColor = UIColor.groupTableViewBackgroundColor()
        titleView.layer.cornerRadius = 4
        titleView.layer.masksToBounds = true
    }
}
tableView.separatorStyle = .None
tableView.dataSource = self
tableView.delegate = self
let cellHeight: CGFloat = 56  // 高度
let cellHeightExpanded: CGFloat = 360  // 展开高度

let cellCount = 24  // cell 数量
var cellStatus = [Bool](count: 24, repeatedValue: false)  // cell 的展开状态

let onlyOneExpanded = true  // 是否只允许一个展开
extension ViewController: UITableViewDataSource, UITableViewDelegate {
    
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return cellCount
    }
    
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! AccordionTableViewCell
        // 定义点击手势
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.tapTitleView(_:)))

        // 利用tag传递 cell 的行数
        cell.titleView.tag = indexPath.row

        // 绑定点击手势
        cell.titleView.addGestureRecognizer(tapGesture)

        return cell
    }
    
    func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        // 根据状态返回 cell 的高度
        return cellStatus[indexPath.row] ? cellHeightExpanded : cellHeight
    }
    
    // 点击标题的回调
    func tapTitleView(sender: UITapGestureRecognizer) {
        if let tag = sender.view?.tag {
            if cellStatus[tag] {
                cellStatus[tag] = false
            } else {
                // 如果只允许一个展开,则重置所有状态为 false
                if onlyOneExpanded {
                    cellStatus = [Bool](count: cellCount, repeatedValue: false)
                }
                cellStatus[tag] = true
            }
            
            // 更新 table view,则会更新高度
            tableView.beginUpdates()
            tableView.endUpdates()

            // 为了点击展开的 cell 不被遮挡,滚动到相应的 cell
            tableView.scrollToRowAtIndexPath(NSIndexPath(forRow: tag, inSection: 0), atScrollPosition: .None, animated: true)
        }
    }
}

成果

这样,UITableView 简单的 Accordion 效果就完成了,让我们看一下最终的代码,和效果截图。

import UIKit

class AccordionTableViewCell: UITableViewCell {

    @IBOutlet weak var wrapView: UIView!
    @IBOutlet weak var titleView: UIView!
    
    override func awakeFromNib() {
        super.awakeFromNib()
        
        self.selectionStyle = .None
        
        wrapView.backgroundColor = UIColor.groupTableViewBackgroundColor()
        wrapView.layer.cornerRadius = 4
        wrapView.layer.masksToBounds = true
        
        titleView.backgroundColor = UIColor.groupTableViewBackgroundColor()
        titleView.layer.cornerRadius = 4
        titleView.layer.masksToBounds = true
    }
}
import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var tableView: UITableView!
    
    let cellHeight: CGFloat = 56
    let cellHeightExpanded: CGFloat = 360
    
    let cellCount = 24
    var cellStatus = [Bool](count: 24, repeatedValue: false)
    
    let onlyOneExpanded = true
    
    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.separatorStyle = .None
        tableView.dataSource = self
        tableView.delegate = self
    }
}

extension ViewController: UITableViewDataSource, UITableViewDelegate {
    
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return cellCount
    }
    
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! AccordionTableViewCell
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.tapTitleView(_:)))
        cell.titleView.tag = indexPath.row
        cell.titleView.addGestureRecognizer(tapGesture)
        return cell
    }
    
    func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        return cellStatus[indexPath.row] ? cellHeightExpanded : cellHeight
    }
    
    func tapTitleView(sender: UITapGestureRecognizer) {
        if let tag = sender.view?.tag {
            if cellStatus[tag] {
                cellStatus[tag] = false
            } else {
                if onlyOneExpanded {
                    cellStatus = [Bool](count: cellCount, repeatedValue: false)
                }
                cellStatus[tag] = true
            }
            
            tableView.beginUpdates()
            tableView.endUpdates()
            tableView.scrollToRowAtIndexPath(NSIndexPath(forRow: tag, inSection: 0), atScrollPosition: .None, animated: true)
        }
    }
}
1.png

Demo地址:https://github.com/4074/UITableViewAccordionDemo

有什么疑问可以在留言中提出哦~~~

上一篇下一篇

猜你喜欢

热点阅读