如何实现可收起和展开的Table Section

如何实现可收起和展开的Table Section,第1张

概述如何实现可收起展开的Table Section 这是一个简单的iOS swift项目,旨在介绍如何实现可收起和展开的table section,并且,项目不需要main storyboard, XIB, 注册nib等,只需要纯的Swfit代码! 项目源代码:https://github.com/jeantimex/ios-swift-collapsible-table-section 如果你希望 如何实现可收起和展开的table Section

这是一个简单的iOS swift项目,旨在介绍如何实现可收起和展开的table section,并且,项目不需要main storyboard,XIB,注册nib等,只需要纯的Swfit代码!

项目源代码:https://github.com/jeantimex/ios-swift-collapsible-table-section

如果你希望获得Swift 3.0的代码,可以在migrate-to-swift-3.0分支里找到,最终将会汇入master分支。

效果


如何实现可收起和展开的table Section? 第一步. 准备数据

假设我们有如下的数据,它已经按照不同的section进行组织和整理,每个section都是一个Section结构(或对象):

struct Section {  var name: String!  var items: [String]!  var collapsed: Bool!  init(name: String,items: [String],collapsed: Bool = false) {    self.name = name    self.items = items    self.collapsed = collapsed  }}var sections = [Section]()sections = [  Section(name: "Mac",items: ["MacBook","MacBook Air","MacBook Pro","iMac","Mac Pro","Mac mini","AccessorIEs","OS X El CAPItan"]),Section(name: "iPad",items: ["iPad Pro","iPad Air 2","iPad mini 4","AccessorIEs"]),Section(name: "iPhone",items: ["iPhone 6s","iPhone 6","iPhone SE","AccessorIEs"])]

collapsed表示当前的section是否被收起或展开,默认下是false,即展开。

第二步. Section header

根据苹果 API reference,我们应该使用UItableVIEwheaderfooterVIEw. 让我们创建一个section header的类来继承它,我们把这个section header类起名为CollapsibletableVIEwheader:

class CollapsibletableVIEwheader: UItableVIEwheaderfooterVIEw {    let TitleLabel = UILabel()    let arrowLabel = UILabel()    overrIDe init(reuseIDentifIEr: String?) {        super.init(reuseIDentifIEr: reuseIDentifIEr)        contentVIEw.addSubvIEw(TitleLabel)        contentVIEw.addSubvIEw(arrowLabel)    }    required init?(coder aDecoder: NSCoder) {        fatalError("init(coder:) has not been implemented")    }}

当用户点击section header的时候我们需要收起或者展开这个section,为了实现这样的效果,让我们借用一下UITapGestureRecognizer. 同时我们需要将这个tap事件通知给table vIEw并让它来更新section的collapsed值。

protocol CollapsibletableVIEwheaderDelegate {    func toggleSection(header: CollapsibletableVIEwheader,section: Int)}class CollapsibletableVIEwheader: UItableVIEwheaderfooterVIEw {    var delegate: CollapsibletableVIEwheaderDelegate?    var section: Int = 0    ...    overrIDe init(reuseIDentifIEr: String?) {        super.init(reuseIDentifIEr: reuseIDentifIEr)        ...        addGestureRecognizer(UITapGestureRecognizer(target: self,action: #selector(CollapsibletableVIEwheader.tapheader(_:))))    }    ...    func tapheader(gestureRecognizer: UITapGestureRecognizer) {        guard let cell = gestureRecognizer.vIEw as? CollapsibletableVIEwheader else {            return        }        delegate?.toggleSection(self,section: cell.section)    }    func setCollapsed(collapsed: Bool) {        // Animate the arrow rotation (see Extensions.swf)        arrowLabel.rotate(collapsed ? 0.0 : CGfloat(M_PI_2))    }}

既然我们不用任何storyboard或者XIB,如何实现自动布局呢?答案是运用NSLayoutConstraintconstraintsWithVisualFormat函数。

overrIDe init(reuseIDentifIEr: String?) {    ...    // arrowLabel must have fixed wIDth and height    arrowLabel.wIDthAnchor.constraintEqualToConstant(12).active = true    arrowLabel.heightAnchor.constraintEqualToConstant(12).active = true    TitleLabel.translatesautoresizingMaskIntoConstraints = false    arrowLabel.translatesautoresizingMaskIntoConstraints = false}overrIDe func layoutSubvIEws() {    super.layoutSubvIEws()    ...    let vIEws = [        "TitleLabel" : TitleLabel,"arrowLabel" : arrowLabel,]    contentVIEw.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat(        "H:|-20-[TitleLabel]-[arrowLabel]-20-|",options: [],metrics: nil,vIEws: vIEws    ))    contentVIEw.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat(        "V:|-[TitleLabel]-|",vIEws: vIEws    ))    contentVIEw.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat(        "V:|-[arrowLabel]-|",vIEws: vIEws    ))}
第三步. UItableVIEw DataSource 以及 Delegate

首先,sections的数量为sections.count:

overrIDe func numberOfSectionsIntableVIEw(tableVIEw: UItableVIEw) -> Int {  return sections.count}

每个section里面cell的数量为:

overrIDe func tableVIEw(tableVIEw: UItableVIEw,numberOfRowsInSection section: Int) -> Int {    return sections[section].items.count}

接下来使用tableVIEw的vIEwForheaderInSection函数来渲染我们的section header:

overrIDe func tableVIEw(tableVIEw: UItableVIEw,vIEwForheaderInSection section: Int) -> UIVIEw? {    let header = tableVIEw.dequeueReusableheaderfooterVIEwWithIDentifIEr("header") as? CollapsibletableVIEwheader ?? CollapsibletableVIEwheader(reuseIDentifIEr: "header")    header.TitleLabel.text = sections[section].name    header.arrowLabel.text = ">"    header.setCollapsed(sections[section].collapsed)    header.section = section    header.delegate = self    return header}

普通的cell就很简单了,没什么好说的:

overrIDe func tableVIEw(tableVIEw: UItableVIEw,cellForRowAtIndexPath indexPath: NSIndexPath) -> UItableVIEwCell {    let cell = tableVIEw.dequeueReusableCellWithIDentifIEr("cell") as UItableVIEwCell? ?? UItableVIEwCell(style: .Default,reuseIDentifIEr: "cell")    cell.textLabel?.text = sections[indexPath.section].items[indexPath.row]    return cell}
最后一步. 如何收起和展开?

思路超级简单!如果该section的collapsed值为true,我们就将这个section里所有cell的高度都设为0,否则为 44.0!

overrIDe func tableVIEw(tableVIEw: UItableVIEw,heightForRowAtIndexPath indexPath: NSIndexPath) -> CGfloat {    return sections[indexPath.section].collapsed! ? 0 : 44.0}

切换收起和展开的函数如下:

extension CollapsibletableVIEwController: CollapsibletableVIEwheaderDelegate {    func toggleSection(header: CollapsibletableVIEwheader,section: Int) {        let collapsed = !sections[section].collapsed        // Toggle collapse        sections[section].collapsed = collapsed        header.setCollapsed(collapsed)        // Adjust the height of the rows insIDe the section        tableVIEw.beginUpdates()        for i in 0 ..< sections[section].items.count {            tableVIEw.reloadRowsAtIndexPaths([NSIndexPath(forRow: i,inSection: section)],withRowAnimation: .automatic)        }        tableVIEw.endUpdates()    }}

注意到我们不是简单的重绘整个section,实际上我们只需要重绘section里的所有cell就好,这样做的好处是避免了section header因重绘时闪烁的效果,最重要是的可以让我们更平滑地处理我们想要的动画效果,例如旋转那个箭头,改变背景颜色等等。

好了就这么多吧,如果你很感兴趣,请参考源码。

更多的关于table section收起和展开的项目

有时候你可能想要在grouped-style的table里实现section的收起和展开,我写了另外一个demo,https://github.com/jeantimex/ios-swift-collapsible-table-section-in-grouped-section. 实现的方法其实很类似。


作者: Yong Su @ Box Inc.

总结

以上是内存溢出为你收集整理的如何实现可收起和展开的Table Section全部内容,希望文章能够帮你解决如何实现可收起和展开的Table Section所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/web/1071473.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-26
下一篇 2022-05-26

发表评论

登录后才能评论

评论列表(0条)

保存