xcode 如何快速制作可扩展和可折叠的 UITableView(父单元格和子单元格)?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/36855851/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 08:45:39  来源:igfitidea点击:

How to make an expandable and collapsable UITableView (parent and child cells) in swift?

iosiphonexcodeswiftuitableview

提问by A.G

I wanted to have a UITableViewwhich is able to expand and collapse while clicking on cells.

我想要一个UITableView能够在单击单元格时展开和折叠的对象。

enter image description here

在此处输入图片说明

When I load the page, I want the Tableview to be expanded like this and function collapse and expand by clicking on the header(see the date).

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

Any help is appreciated.

任何帮助表示赞赏。

回答by A.G

Thanks everyone. I have solved the problem at last.This is the final sample code.

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

1) //Arrays for header and Child cells.

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

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

//Section index reference

//段索引参考

var selectedIndexPathSection:Int = -1

2) Added Two custom cells. - one as header and other as Cell.

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

//  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)   

    }    
}

Child cell:

子单元格:

//  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) On View Controller:

3)在视图控制器上:

//  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.
    }    
}

The sample can be downloaded @ https://github.com/alvinreuben/Expand-ColllapseTableView

示例可以在@ https://github.com/alvinreuben/Expand-CollapseTableView下载

回答by Surjeet Rajput

with the help of below method you can do that

借助以下方法,您可以做到

for objective-c

对于目标-c

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

for swift

为了迅速

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

just change the height for a row when its get clicked and reload the section.

只需在单击并重新加载该部分时更改行的高度即可。

when you design any cell in storyboard don't put bottom constraint on the expandable part.just put top and height constraint.Hope this help :)

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

回答by Nischal Hada

**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()

        }

    }