繁体   English   中英

Swift - 选择 TableView 单元格时的动画 (didSelectRowAtIndexPath)

[英]Swift - Animating When TableView Cell Selected (didSelectRowAtIndexPath)

我一直在尝试在我的 tableviewcell 被选中时为它的内容设置动画,但我遇到了问题。 我读过一些地方,你不能在 didSelectRowAtIndexPath 中运行 animatewithduration 或者至少如果你这样做,它不会动画。 我下面的代码似乎就是这种情况,视图移动但没有动画。

我曾尝试将逻辑合并到 willDisplayCell 中以监视选择但无济于事,因此,如果有人能够为我找到正确的解决方案,我会很高兴,因为尽管进行了大量搜索,但答案似乎不可用:

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    let currentCellDescriptor = getCellDescriptorForIndexPath(indexPath)
    let cell = tableView.dequeueReusableCellWithIdentifier(currentCellDescriptor["cellIdentifier"] as! String, forIndexPath: indexPath) as! CustomCell
    let indexOfTappedRow = visibleRowsPerSection[indexPath.section][indexPath.row]
    if cellDescriptors[indexPath.section][indexOfTappedRow]["isExpandable"] as! Bool == true {
        if cellDescriptors[indexPath.section][indexOfTappedRow]["isExpanded"] as! Bool == false {


            // INTERESTING BIT: Animates cell contents to Right
            if currentCellDescriptor["cellIdentifier"] as! String == "CellHeader" {
                UIView.animateWithDuration(0.5, delay: 0, usingSpringWithDamping: 0.7, initialSpringVelocity: 12, options: .CurveLinear, animations: {
                    cell.headerTitleLeftConstraint.priority = 999
                    cell.headerTitleRightConstraint.priority = 1
                    cell.layoutIfNeeded()
                    }, completion: nil)
            }

       } else if cellDescriptors[indexPath.section][indexOfTappedRow]["isExpanded"] as! Bool == true {
           // MARK: Animates cell contents back to left
           if currentCellDescriptor["cellIdentifier"] as! String == "CellHeader" {
                UIView.animateWithDuration(0.5, delay: 0, usingSpringWithDamping: 0.7, initialSpringVelocity: 12, options: .CurveLinear, animations: {
                    cell.headerTitleLeftConstraint.priority = 1
                    cell.headerTitleRightConstraint.priority = 999
                    cell.layoutIfNeeded()
                     }, completion: nil)
                    }
            }

首先,不要在这里使用dequeueReusableCellWithIdentifier 它将使用屏幕上不可见的单元格并准备显示它。 你想要的是cellForRowAtIndexPath ,它返回一个已经在给定indexPath屏幕上的单元格。

然后我知道您想使用 2 个约束并为布局更改设置动画。 为此,动画应该只包含layoutIfNeeded

cell.headerTitleLeftConstraint.priority = 999
cell.headerTitleRightConstraint.priority = 1
UIView.animateWithDuration(0.5, delay: 0, usingSpringWithDamping: 0.7, initialSpringVelocity: 12, options: .CurveLinear, animations: {
                cell.layoutIfNeeded()
                }, completion: nil)

我还建议您将此逻辑从控制器转移到您的CustomCell类。 例如,使用selected属性和setSelected(animated: Bool)来直观地处理状态变化。

在 Tanguy 的帮助下,这就是我们的样子。 我仍然有一些动画问题,因为表格本身实际上不会为下面的下一个单元格设置动画,但我会改进该代码并使其工作。 认为这适合现在的目的,因此值得发布以展示解决方案本身。 谢谢!!

 override func setSelected(selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)
        // Adjusts constraints everytime switch is tapped
        isLeftAligned = !isLeftAligned
            if userHanded == "Right" {
            UIView.animateWithDuration(0.5, delay: 0, usingSpringWithDamping: 0.7, initialSpringVelocity: 12, options: .CurveLinear, animations: {
                self.leftHandedHeaderConstraint.priority = (self.isLeftAligned) ? 1 : 999
                self.rightHandedHeaderConstraint.priority = (self.isLeftAligned) ? 999 : 1
                self.layoutIfNeeded()
            }, completion: nil)

        } else if userHanded == "Left" {
            UIView.animateWithDuration(0.5, delay: 0, usingSpringWithDamping: 0.7, initialSpringVelocity: 12, options: .CurveLinear, animations: {
                self.leftHandedHeaderConstraint.priority = (self.isLeftAligned) ? 999 : 1
                self.rightHandedHeaderConstraint.priority = (self.isLeftAligned) ? 1 : 999
                self.layoutIfNeeded()
                }, completion: nil)
        }
}

您不需要使用UIView.animate(...) UITableView默认提供动画更新。 更改约束后,您可以通过调用:

tableView.performBatchUpdates(nil, completion: nil)     

不要忘记在创建时给你的 height 属性一个低于.required优先级。 否则 AutoLayout 将在更新时破坏约束(您可以在调试器中观察到这一点)。 而不是将约束的优先级设置为999或类似的东西,您应该使用UILayoutPriority静态属性以获得更具可读性的代码。

/// Set this wherever you create your height constraint, e.g. in your custom cell's class.
heightConstraint?.priority = .defaultHigh

didSelectRowAt的完整代码如下所示:

    let expandedHeight: CGFloat = 500
    let defaultHeight: CGFloat = 85

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
      guard let cell = tableView.cellForRow(at: indexPath) as? YourCustomTableViewCell else { return }

      /// Save the status of your cell in a property of your view model.
      if viewModel[indexPath.row].isFullsize {
        cell.heightConstraint?.constant = defaultHeight
        viewModel[indexPath.row].isFullsize = false
      } else {
        cell.heightConstraint?.constant = expandedHeight
        viewModel[indexPath.row].isFullsize = true
      }

      /// Call this for an animated update (since iOS 11)
      tableView.performBatchUpdates(nil, completion: nil)

      /// For the same result you could also use
      /// tableView.beginUpdates()
      /// tableView.endUpdates()
      /// ...but the docs say that this will become deprecated soon

      /// Scrolls to your selected cell's top
      tableView.scrollToRow(at: indexPath, at: .top, animated: true)
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM