【问题标题】:Expand and contract tableview cell when tapped, in swift延长和收缩TableView单元格时,迅速
【发布时间】:2015-10-27 09:11:10
【问题描述】:

我试图在点击时展开一个表格视图单元格。然后,当它再次被点击时,我希望它恢复到原来的状态。

如果单元格A 展开并点击单元格B,我希望单元格A 收缩和单元格B 同时展开。因此,在任何给定时刻,只有一个单元格可以处于展开状态。

我当前的代码:

class MasterViewController: UITableViewController {
   var isCellTapped = false
   var currentRow = -1


   override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        selectedRowIndex = indexPath
        tableView.beginUpdates()
        tableView.endUpdates()
    }


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

    if indexPath.row == selectedRowIndex.row {
        if isCellTapped == false {
            isCellTapped = true
            return 140
        } else if isCellTapped == true {
            isCellTapped = false
            return 70
        }

    }

    return 70
}

当前代码在以下情况下运行良好:

  • 点击一行(它会展开)
  • 你再次点击它(它会收缩)

在以下情况下失败:

  • 点击一行(它会展开)
  • 您点击另一行(它会收缩,但另一行不会展开)

我该如何解决这个问题?

【问题讨论】:

  • 你想达到什么目的?使用 UITableView? 的手风琴菜单(下拉菜单)
  • 是的@VictorSigler,类似的东西。你认为使用 UITableView 可以做到吗?或者还有其他更适合该任务的类吗?
  • 是的,你可以@Diego 看到我的答案。
  • @VictorSigler 我真正需要的一件事是“扩展”状态在任何给定时刻仅是一个单元格的属性。如果 cellA 展开而 cellB 被点击,则 cellA 必须收缩而 cellB 展开。
  • 您可以毫无问题地做到这一点,请参阅我更新的答案,但我强烈建议您查看我的 repo 以了解更多关于使用 UITableView 的手风琴菜单的信息

标签: swift uitableview


【解决方案1】:

您需要考虑在点击另一行时需要更新您选择的行,请参见以下代码:

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

    if indexPath.row == selectedRowIndex {
        return 140
    }
    return 44
}

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

    if selectedRowIndex != indexPath.row {

        // paint the last cell tapped to white again
        self.tableView.cellForRowAtIndexPath(NSIndexPath(forRow: self.selectedRowIndex, inSection: 0))?.backgroundColor = UIColor.whiteColor()

        // save the selected index 
        self.selectedRowIndex = indexPath.row

        // paint the selected cell to gray
        self.tableView.cellForRowAtIndexPath(indexPath)?.backgroundColor = UIColor.grayColor()

        // update the height for all the cells
        self.tableView.beginUpdates()
        self.tableView.endUpdates()
    }
}

编辑:

要处理选择并再次点击的单元格返回其原始状态,您需要检查一些条件,如下所示:

var thereIsCellTapped = false
var selectedRowIndex = -1

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

    if indexPath.row == selectedRowIndex && thereIsCellTapped {
        return 140
    }

    return 44
}

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

    self.tableView.cellForRowAtIndexPath(indexPath)?.backgroundColor = UIColor.grayColor()

    // avoid paint the cell is the index is outside the bounds
    if self.selectedRowIndex != -1 {
        self.tableView.cellForRowAtIndexPath(NSIndexPath(forRow: self.selectedRowIndex, inSection: 0))?.backgroundColor = UIColor.whiteColor()
    }

    if selectedRowIndex != indexPath.row {
        self.thereIsCellTapped = true
        self.selectedRowIndex = indexPath.row
    }
    else {
        // there is no cell selected anymore
        self.thereIsCellTapped = false
        self.selectedRowIndex = -1
    }

    self.tableView.beginUpdates()
    self.tableView.endUpdates()
}

通过您的didSelectRowAtIndexPathheightForRowAtIndexPath 函数中的上述修改,您可以看到当一个单元格被点击时,它的背景颜色会在它的高度增加时变为灰色,而当另一个单元格被点击时,该单元格被涂成白色并且一次又一次地点击到灰色,只允许一次点击一个单元格。

虽然您可以在我创建的repo 中受益并学习如何制作手风琴菜单,但我计划很快更新以处理更好的结果,它可以使用UITableView 进行处理随心所欲。

对存储库有任何疑问,您可以在此处发布。

希望对你有所帮助。

【讨论】:

  • 您的代码出现两个错误:“NSIndexPath 不能转换为 int”和“无法将 Int 的值分配给 NSIndexPath 类型的值”。这些发生在尝试“再次将点击的单元格绘制为白色”以及“保存所选索引”时。有什么线索吗?
  • 我解决了这两个问题,只是我的一个愚蠢的错误。我的问题是现在。您的代码现在运行良好,但是当点击已展开的单元格时,该单元格不会回到其原始(收缩)状态。
  • @DiegoPetrucci 查看我的更新答案以澄清您的疑问。
  • @VictorSigler,有没有什么办法可以让单元格在被选中之前仍然展开? Because using your code, it expand selected cell but, it turn back to original when other cell is selected.
  • @ThihaAung 在这种情况下,答案是一次只支持一个扩展的单元格,但您可以在此存储库中查看我的代码以获取更多信息github.com/Vkt0r/AccordionMenuSwift
【解决方案2】:

一次只扩展一个单元格的简单方法:

斯威夫特 3

class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {  

var selectedRowIndex = -1  
@IBOutlet weak var tableView: UITableView!

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        if indexPath.row == selectedRowIndex {
            return 90 //Expanded
        }
        return 40 //Not expanded
    }

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        if selectedRowIndex == indexPath.row {
            selectedRowIndex = -1
        } else {
            selectedRowIndex = indexPath.row
        }
        tableView.reloadRows(at: [indexPath], with: .automatic)
    }
}  

此代码将展开单击的单元格并用动画关闭先前打开的单元格。

【讨论】:

  • 谢谢它工作得很好,当我尝试在“return 90 //Expanded”语句中放置一个断点时它执行了3次,你能告诉我为什么吗?
  • 对表中的每一行执行的行高度
  • @MarkKazakov 我可以问一个与可扩展细胞有关的问题吗?
  • @Newbie 是的,当然
  • @MarkKazakov 谢谢。这是我的问题链接我怎样才能做到这一点? stackoverflow.com/questions/61637065/…
【解决方案3】:

UITableViewCell

import UIKit

protocol HierarchyTableViewCellDelegate {
   func didTapOnMoreButton(cell:HierarchyTableViewCell)
}

class HierarchyTableViewCell: UITableViewCell {

@IBOutlet weak var viewBtn: UIButton!

//MARK:- CONSTANT(S)
var delegate:HierarchyTableViewCellDelegate!

override func awakeFromNib() {
    super.awakeFromNib()
    // Initialization code
}
@IBAction func actionViewButtonTapped(_ sender: Any) {
     delegate.didTapOnMoreButton(cell: self)
 }
}

UIViewController:

import UIKit

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

@IBOutlet weak var tableViewObj: UITableView!
var HierarchyListArr = NSArray()
var selectedIndex:Int?

func numberOfSections(in tableView: UITableView) -> Int {
    return 1
}

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

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableViewObj.dequeueReusableCell(withIdentifier: "HierarchyTableViewCell", for: indexPath) as! HierarchyTableViewCell
    cell.delegate = self
 if let index = selectedIndex,indexPath.row == index{
        cell.viewBtn.isSelected = true
    }else{
        cell.viewBtn.isSelected = false
    }

    return cell
}

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    if let index = selectedIndex,indexPath.row == index{
        return 190
    }
    return 80
}
}

extension ViewController: HierarchyTableViewCellDelegate{
func didTapOnMoreButton(cell: HierarchyTableViewCell) {
    guard let index = tableViewObj.indexPath(for: cell)else{return}
    if selectedIndex == index.row{
        selectedIndex = -1
    }else{
        selectedIndex = index.row
    }
    tableViewObj.reloadRows(at: [index], with: .fade)
}
}

【讨论】:

    猜你喜欢
    • 2021-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-21
    相关资源
    最近更新 更多