在Swift中点击时展开单元格

use*_*428 14 uitableview ios swift

我一直在尝试在我的应用程序中实现一个功能,以便当用户点击我的表格视图中的单元格时,单元格向下展开以显示注释.我在Objective-C中找到了很多这样的例子,但我还没有找到任何Swift.

这个例子看起来很完美:手风琴表格单元格 - 如何动态扩展/收缩uitableviewcell?

我试图将其翻译成Swift:

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

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    if selectedRowIndex == selectedRowIndex.row && indexPath.row == selectedRowIndex.row {
        return 100
    }
    return 70
}
Run Code Online (Sandbox Code Playgroud)

然而,这似乎使应用程序崩溃.

有任何想法吗?

编辑:

这是我的cellForRowAtIndexPath代码:

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    var cell:CustomTransactionTableViewCell = self.tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as CustomTransactionTableViewCell

    cell.selectionStyle = UITableViewCellSelectionStyle.None

    if tableView == self.searchDisplayController?.searchResultsTableView {
        cell.paymentNameLabel.text = (searchResults.objectAtIndex(indexPath.row)) as? String
        //println(searchResults.objectAtIndex(indexPath.row))
        var indexValue = names.indexOfObject(searchResults.objectAtIndex(indexPath.row))
        cell.costLabel.text = (values.objectAtIndex(indexValue)) as? String
        cell.dateLabel.text = (dates.objectAtIndex(indexValue)) as? String

        if images.objectAtIndex(indexValue) as NSObject == 0 {
            cell.paymentArrowImage.hidden = false
            cell.creditArrowImage.hidden = true
        } else if images.objectAtIndex(indexValue) as NSObject == 1 {
            cell.creditArrowImage.hidden = false
            cell.paymentArrowImage.hidden = true
        }
    } else {
        cell.paymentNameLabel.text = (names.objectAtIndex(indexPath.row)) as? String
        cell.costLabel.text = (values.objectAtIndex(indexPath.row)) as? String
        cell.dateLabel.text = (dates.objectAtIndex(indexPath.row)) as? String

        if images.objectAtIndex(indexPath.row) as NSObject == 0 {
            cell.paymentArrowImage.hidden = false
            cell.creditArrowImage.hidden = true
        } else if images.objectAtIndex(indexPath.row) as NSObject == 1 {
            cell.creditArrowImage.hidden = false
            cell.paymentArrowImage.hidden = true
        }
    }
    return cell
}
Run Code Online (Sandbox Code Playgroud)

以下是插座设置:

在此输入图像描述

Luc*_*rro 17

让我开始工作需要花费很多时间.以下是我如何解决它.

PS:@ rdelmar的代码的问题在于他假设你section的桌子里只有一个,所以他只是在比较indexPath.row.如果您有多个部分(或者您希望以后考虑扩展代码),则应比较整个索引,如下所示:

1)您需要一个变量来判断选择了哪一行.我看到你已经这样做了,但你需要将变量返回到一致的"未选中"状态(当用户关闭所有单元格时).我认为最好的方法是通过可选:

var selectedIndexPath: NSIndexPath? = nil
Run Code Online (Sandbox Code Playgroud)

2)您需要确定用户何时选择一个单元格.didSelectRowAtIndexPath是显而易见的选择.您需要考虑三种可能的结果:

  1. 用户正在点击一个单元格,另一个单元格被扩展
  2. 用户正在点击一个单元格,没有单元格被扩展
  3. 用户正在点击已扩展的单元格

对于每种情况,我们检查selectedIndexPath是否等于nil(没有扩展的单元格),等于抽头行的indexPath(已经扩展的相同单元格)或者与indexPath不同(另一个单元格被扩展).我们相应地调整selectedIndexPath.此变量将用于检查每行的右rowHeight.你在评论中提到didSelectRowAtIndexPath"似乎没有被称为".你在使用println()并检查控制台是否被调用?我在下面的代码中包含了一个.

PS:这不起作用,tableView.rowHeight因为显然,在更新tableView中的所有行之前,只有Swift检查一次rowHeight.

最后但并非最不重要的是,我reloadRowsAtIndexPath只使用重新加载所需的行.但是,因为我知道它会重绘表格,必要时重新布局,甚至动画更改.注意[indexPath]括号之间是因为此方法要求输入NSIndexPath数组:

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        println("didSelectRowAtIndexPath was called")
        var cell = tableView.cellForRowAtIndexPath(indexPath) as! MyCustomTableViewCell
        switch selectedIndexPath {
        case nil:
            selectedIndexPath = indexPath
        default:
            if selectedIndexPath! == indexPath {
                selectedIndexPath = nil
            } else {
                selectedIndexPath = indexPath
            }
        }
        tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
}
Run Code Online (Sandbox Code Playgroud)

3)第三步也是最后一步,Swift需要知道何时将每个值传递给单元格高度.我们在这里进行类似的检查,使用if/else.我知道你可以让代码更短,但我正在输入所有内容,以便其他人也能轻松理解它:

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        let smallHeight: CGFloat = 70.0
        let expandedHeight: CGFloat = 100.0
        let ip = indexPath
        if selectedIndexPath != nil {
            if ip == selectedIndexPath! {
                return expandedHeight
            } else {
                return smallHeight
            }
        } else {
            return smallHeight
        }
    }
Run Code Online (Sandbox Code Playgroud)

现在,如果上述方法无法解决问题,请注意您的代码可能导致问题的原因:

var cell:CustomTransactionTableViewCell = self.tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as CustomTransactionTableViewCell
Run Code Online (Sandbox Code Playgroud)

我不知道这是不是问题,但self不一定是必要的,因为你可能会把这个代码放在你的(Custom)TableViewController中.此外,如果您正确地强制从出队中强制转换单元格,您可以信任Swift的推理,而不是指定您的变量类型.强制转换是as!在下面的代码中:

var cell = tableView.dequeueReusableCellWithIdentifier("CellIdentifier" forIndexPath: indexPath) as! CustomTransactionTableViewCell
Run Code Online (Sandbox Code Playgroud)

但是,您绝对需要设置该标识符.转到您的故事板,选择具有所需单元格的tableView,以及您需要的TableViewCell的子类(可能CustomTransactionTableViewCell在您的情况下).现在选择TableView中的单元格(检查是否选择了正确的元素.最好通过编辑器>显示文档大纲打开文档大纲).选中单元格后,转到右侧的"属性"检查器,然后键入Identifier名称.

您也可以尝试注释掉cell.selectionStyle = UITableViewCellSelectionStyle.None以检查是否以任何方式阻止选择(这样,如果选中它们,则在点击时单元格会改变颜色).

祝你好运,交配.


rde*_*mar 7

if语句中的第一个比较永远不会成立,因为您将indexPath与整数进行比较.您还应该使用不能在表中的行值初始化selectedRowIndex变量,例如-1,因此在表首次加载时不会展开任何内容.

var selectedRowIndex: NSIndexPath = NSIndexPath(forRow: -1, inSection: 0)

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    if indexPath.row == selectedRowIndex.row {
        return 100
    }
    return 70
}
Run Code Online (Sandbox Code Playgroud)

Swift 4.2 var selectedRowIndex: NSIndexPath = NSIndexPath(row: -1, section: 0)


the*_*eDC 6

我建议通过修改高度布局约束来解决这个问题

class ExpandableCell: UITableViewCell {

@IBOutlet weak var img: UIImageView!


@IBOutlet weak var imgHeightConstraint: NSLayoutConstraint!


var isExpanded:Bool = false
    {
    didSet
    {
        if !isExpanded {
            self.imgHeightConstraint.constant = 0.0

        } else {
            self.imgHeightConstraint.constant = 128.0
        }
    }
}

}
Run Code Online (Sandbox Code Playgroud)

然后,在 ViewController 中:

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
    super.viewDidLoad()
    self.tableView.delegate = self
    self.tableView.dataSource = self
    self.tableView.estimatedRowHeight = 2.0
    self.tableView.rowHeight = UITableViewAutomaticDimension
    self.tableView.tableFooterView = UIView()
}


// TableView DataSource methods
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 3
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell:ExpandableCell = tableView.dequeueReusableCell(withIdentifier: "ExpandableCell") as! ExpandableCell
    cell.img.image = UIImage(named: indexPath.row.description)
    cell.isExpanded = false
    return cell
}

// TableView Delegate methods
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

    guard let cell = tableView.cellForRow(at: indexPath) as? ExpandableCell
        else { return }

        UIView.animate(withDuration: 0.3, animations: {
            tableView.beginUpdates()
            cell.isExpanded = !cell.isExpanded
            tableView.scrollToRow(at: indexPath, at: UITableViewScrollPosition.top, animated: true)
            tableView.endUpdates()

        })

    }




func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
    guard let cell = tableView.cellForRow(at: indexPath) as? ExpandableCell
        else { return }
    UIView.animate(withDuration: 0.3, animations: {
        tableView.beginUpdates()
        cell.isExpanded = false
        tableView.endUpdates()
    })
}
}
Run Code Online (Sandbox Code Playgroud)

完整教程在这里


Jus*_*her 5

一种不同的方法是在导航堆栈中推送一个新的视图控制器,并使用转换来扩展效果。好处是 SoC(关注点分离)。两种模式的示例 Swift 2.0 项目。