如何在swift中制作可扩展和可折叠的UITableView(父级和子级单元格)?

时间:2016-04-26 05:21:20

标签: ios iphone xcode swift uitableview

我希望有一个UITableView能够在点击单元格时展开和折叠。

enter image description here

当我加载页面时,我希望像这样展开Tableview,并通过单击标题来折叠和展开(参见日期)。

感谢任何帮助。

3 个答案:

答案 0 :(得分:6)

谢谢大家。我终于解决了这个问题。这是最终的示例代码。

1)//标题和子单元格的数组。

var topItems = [String]()
var subItems = [String]()

//部分索引参考

var selectedIndexPathSection:Int = -1

2)添加了两个自定义单元格。 - 一个作为标题,另一个作为Cell。

//  AgendaListHeaderTableViewCell.swift

import UIKit

class AgendaListHeaderTableViewCell: UITableViewCell {

    @IBOutlet weak var agendaDateLabel: UILabel!
    @IBOutlet weak var expandCollapseImageView: UIImageView!
    @IBOutlet weak var headerCellButton: UIButton!    

    override func awakeFromNib() {
        super.awakeFromNib()

    }

    override func setSelected(selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)   

    }    
}

儿童细胞:

//  AgendaListTableViewCell.swift

import UIKit

class AgendaListTableViewCell: UITableViewCell {

    @IBOutlet weak var agendaListContainerView: UIView!
    @IBOutlet weak var moduleListTitleLabel: UILabel!
    @IBOutlet weak var moduleDueOnStatusLabel: UILabel!
    @IBOutlet weak var moduleLocationLabel: UILabel!
    @IBOutlet weak var moduleStatusLabel: UILabel!
    @IBOutlet weak var moduleDownLoadStatusImageView: UIImageView!
    @IBOutlet weak var moduleStatusLeftSideLabel: UILabel!


    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
        agendaListContainerView.layer.cornerRadius =  3.0

        moduleStatusLabel.layer.borderWidth = 0.5
        moduleStatusLabel.layer.borderColor = UIColor.clearColor().CGColor
        moduleStatusLabel.clipsToBounds = true
        moduleStatusLabel.layer.cornerRadius =  5.0

    }

    override func setSelected(selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

    }
}

3)在View Controller上:

//  AgendaListViewController.swift

import UIKit

class AgendaListViewController: UIViewController,UITableViewDataSource,UITableViewDelegate {

    @IBOutlet weak var agendaListTableView: UITableView!

    var appUIColor:UIColor = UIColor.brownColor()
    var topItems = [String]()
    var subItems = [String]()
    var selectedIndexPathSection:Int = -1

    override func viewDidLoad() {
        super.viewDidLoad()

        topItems = ["26th April 2017","27th April 2017","28th April 2017","29th April 2017","30th April 2017"]
        subItems = ["Monday","TuesDay","WednessDay"]

    }
    override func viewWillAppear(animated: Bool) {
        self.title = "AGENDA VIEW"
        self.automaticallyAdjustsScrollViewInsets =  false
        agendaListTableView.tableFooterView = UIView(frame: CGRectZero)
    }
//tableview delegate methods    
    func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {

        return 85;

    }
    func numberOfSectionsInTableView(tableView: UITableView) -> Int
    {
        return topItems.count
    }
    func tableView(tableView: UITableView, estimatedHeightForHeaderInSection section: Int) -> CGFloat {

        return 35
    }
    func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {

        let headerCell = tableView.dequeueReusableCellWithIdentifier("agendaTableViewHeaderCellD") as! AgendaListHeaderTableViewCell
        headerCell.agendaDateLabel.text = topItems[section]as String

        //a buttton is added on the top of all UI elements on the cell and its tag is being set as header's section.

        headerCell.headerCellButton.tag =  section+100
        headerCell.headerCellButton.addTarget(self, action: "headerCellButtonTapped:", forControlEvents: UIControlEvents.TouchUpInside)

        //minimize and maximize image with animation.
        if(selectedIndexPathSection == (headerCell.headerCellButton.tag-100))
        {
            UIView.animateWithDuration(0.3, delay: 1.0, usingSpringWithDamping: 5.0, initialSpringVelocity: 5.0, options: UIViewAnimationOptions.TransitionCrossDissolve, animations: {
                headerCell.expandCollapseImageView.image =  UIImage(named: "maximize")
                }, completion: nil)
        }
        else{

            UIView.animateWithDuration(0.3, delay: 1.0, usingSpringWithDamping: 5.0, initialSpringVelocity: 5.0, options: UIViewAnimationOptions.TransitionCrossDissolve, animations: {
                headerCell.expandCollapseImageView.image =  UIImage(named: "minimize")
                }, completion: nil)
        }

        return headerCell
    }

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        if( selectedIndexPathSection == section){
            return 0
        }
        else {
            return self.subItems.count
        }
    }
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

        let childCell = tableView.dequeueReusableCellWithIdentifier("agendaTableViewCellID", forIndexPath: indexPath) as! AgendaListTableViewCell
        childCell.moduleListTitleLabel.text = subItems[indexPath.row] as? String
        childCell.moduleLocationLabel.text = subItems[indexPath.row] as? String
        childCell.moduleDueOnStatusLabel.text = subItems[indexPath.row] as? String

        return childCell
    }

    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {


    }
    //button tapped on header cell
    func headerCellButtonTapped(sender:UIButton)
    {
        if(selectedIndexPathSection == (sender.tag-100))
        {
            selectedIndexPathSection = -1
        }
        else   {
            print("button tag : \(sender.tag)")
            selectedIndexPathSection = sender.tag - 100
        }

        //reload tablview
        UIView.animateWithDuration(0.3, delay: 1.0, options: UIViewAnimationOptions.TransitionCrossDissolve , animations: {
            self.agendaListTableView.reloadData()
            }, completion: nil)

    }   
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }    
}

样本可以下载@ https://github.com/alvinreuben/Expand-ColllapseTableView

答案 1 :(得分:0)

借助以下方法你可以做到

for objective-c

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

for swift

func tableView(_ tableView: UITableView,heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat

只需在点击一行时更改行的高度,然后重新加载该部分。

当你在故事板中设计任何单元格时,不要在可扩展部分上放置底部约束。只需要放置顶部和高度约束。希望这个帮助:)

答案 2 :(得分:0)

**Try to implement below**

import UIKit


class BankDepositsHistoryVC: UIViewController {


    @IBOutlet weak var tableView: UITableView!

    let NORMAL_HEIGHT:CGFloat = 90
    let EXPANDABLE_HEIGHT:CGFloat = 200

    var SECTION_OTHER_CARDS = 0
    var expandableRow:Int = Int()


    override func viewDidLoad() {
        super.viewDidLoad()

        self.expandableRow =  self.historyData.count + 1 // initially there is no expanded cell
        self.tableView.reloadData()


    }




    // MARK: - TableViewDelegate Setup

    extension BankDepositsHistoryVC : UITableViewDelegate,UITableViewDataSource {

        func numberOfSectionsInTableView(tableView: UITableView) -> Int{
            return 1

        }

        func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return self.historyData.count
        }




        func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat{

            let value = indexPath.section
            let row = indexPath.row


            switch (value){

            case SECTION_OTHER_CARDS:

                switch (row){

                case self.expandableRow:
                    return EXPANDABLE_HEIGHT

                default:
                    return NORMAL_HEIGHT

                }

            default:
                return 0
            }

        }



        func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

            let cell = tableView.dequeueReusableCellWithIdentifier("DepositsHistoryCell", forIndexPath: indexPath) as! DepositsHistoryCell
            cell.selectionStyle = UITableViewCellSelectionStyle.None
            return cell
        }


        func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath){

            self.expandableRow =  indexPath.row // provide row to be expanded
            //self.tableView.reloadSections(NSIndexSet(index: indexPath.row), withRowAnimation: UITableViewRowAnimation.Fade)
            self.tableView.reloadData()

        }

    }