Swift在TableViewCell中替换内容的最佳方法是什么

时间:2017-09-30 14:28:18

标签: ios swift tableview

我想在GIF中做点什么 我尝试了两种方法,一种是隐藏选择行并显示其他元素的元素,但这不是很优雅,并且不能很好地工作 第二个是创建2个视图,一个带有标签,另一个带有按钮,将它们作为子视图添加到cell.contentView,但是由于它们显示错误数据而导致其他单元格出现问题。我该如何重新创建这样的东西?

enter image description here

2 个答案:

答案 0 :(得分:2)

我认为这样的事情会起作用:

  1. 使用2个不同的UITableViewCells:将它们添加到故事板中的表视图并单独设计,也可以为它们使用2个不同的UITableViewCell子类

  2. 在tableview的数据源类中有一个数组,它将定义每行中单元格的类型(例如,最简单的解决方案是整数数组,值为0表示第一个单元格, 1表示第二个单元格

  3. 初始化该行,每行为0,

  4. tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell

    • if cellTypes [indexPath.row] == 0 - >返回第一个类型的单元格
    • if cellTypes [indexPath.row] == 1 - >返回第二种类型的单元格
  5. tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)

    • 切换数组中的单元格类型
    • 使用动画重新加载行,例如你可以使用.fade或.left或.right等。
  6. tableView.reloadRows(at: [indexPath], with: .fade)

    编辑:您的解决方案也很好,但是当单元格出列时它可能会导致问题,因此如果具有错误子视图的单元格出列,那么您需要在cellForRowAt indexPath数据源中重新切换子视图方法

    EDIT2:我花了一些时间,我在Xcode中尝试了我的解决方案。这是我的tableview控制器的代码:

    class TableViewController: UITableViewController {
    
        private var cellTypes: [Int] = [1, 1, 1, 1, 1, 1]
    
        public override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return self.cellTypes.count
        }
    
        public override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
            return 56.0
        }
    
        public override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            if self.cellTypes[indexPath.row] == 1 {
                return tableView.dequeueReusableCell(withIdentifier: "Cell1", for: indexPath)[![enter image description here][1]][1]
            } else {
                return tableView.dequeueReusableCell(withIdentifier: "Cell2", for: indexPath)
            }
        }
    
        public override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
            tableView.deselectRow(at: indexPath, animated: true)
    
            if self.cellTypes[indexPath.row] == 1 {
                self.cellTypes[indexPath.row] = 2
                tableView.reloadRows(at: [indexPath], with: .fade)
            } else {
                self.cellTypes[indexPath.row] = 1
                tableView.reloadRows(at: [indexPath], with: .right)
            }
        }
    
    }
    

    以下是它在iOS模拟器中的工作原理:

    enter image description here

答案 1 :(得分:1)

我相信你在关于在细胞内创建2个独立视图的正确轨道;一个用于显示3个按钮(立即播放,播放下一个等),一个用于显示歌曲的详细信息(歌曲名称,歌手姓名等)。

为了不混淆帧或约束(如果你使用的是Autolayout),这里的主要技巧是创建包含按钮的视图的快照并将其移动到结尾细胞。

如上所述,您应该有2个单独的视图。我打电话给他们:

  • infoView :包含2个标签的视图,显示歌曲和歌手的名字。
  • actionsView :查看具有3个播放操作按钮的视图。 (现在,下一个,最后等)

以下是用户点击单元格时应该执行的操作:

  1. 检查是否未选择单元格。如果不是,请隐藏 infoView 并显示 actionView
  2. 如果选择了单元格:
    • 取消选择单元格。
    • 使用 actionsView 创建快照,相应地设置其框架,以便遮挡真正的 actionsView
    • actionView isHidden 属性设置为 true
    • infoView isHidden 属性设置为 false
    • 在动画块中将快照的 frame.origin.x 值设置为 contentView maxX ,以便&#39 ; ll顺利地移动到单元格的右侧。
    • 在动画结束时,从视图层次结构中删除快照。
  3. 我创建了一个单元类并定义了一个执行这些步骤的方法:

    public class SongCell: UITableViewCell {
    
      @IBOutlet fileprivate weak var infoView: UIView!
      @IBOutlet fileprivate weak var actionsView: UIView!
    
      ...
    
      public func showActions(_ show: Bool) {
        switch show {
        case true:
          infoView.isHidden = true
          actionsView.isHidden = false
    
        case false:
          if let snapshot = actionsView.snapshotView(afterScreenUpdates: true) {
            snapshot.frame = actionsView.frame
            contentView.addSubview(snapshot)
    
            actionsView.isHidden = true
            infoView.isHidden = false
    
            UIView.animate(withDuration: 0.25, animations: {
              snapshot.frame.origin.x = self.contentView.frame.maxX
    
            }, completion: { _ in
              snapshot.removeFromSuperview()
            })
          }
          else {
            infoView.isHidden = false
            actionsView.isHidden = true
          }
        }
      }
    }
    

    以下是我在模拟器上的外观:

    enter image description here

    您可以从here下载项目。