如何在握住它时逐渐增加tableview单元的大小

我想做什么(逐字):保持一个tableview单元格指定的时间。 一旦达到该时间段,细胞高度逐渐增加。 当我松开手指时,细胞高度停止增长。

我拥有:我有几个tableViewCells。 使用以下方法在单元格上按下指定的时间后:

let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: Selector("longPress:")) longPressRecognizer.minimumPressDuration = 1.0s longPressRecognizer.delegate = self self.view.addGestureRecognizer(longPressRecognizer) 

我想增加细胞高度。 但是,如果不知道触摸位于哪一行,我就无法做到,所以我起身到这里:

 func longPress(longPressGestureRecognizer: UILongPressGestureRecognizer) { if longPressGestureRecognizer.state == UIGestureRecognizerState.began { let touchPoint = longPressGestureRecognizer.location(in: self.tableView) if let indexPath = tableView.indexPathForRow(at: touchPoint) { //let cell = tableView.cellForRow(at: indexPath) } } } 

我想过控制rowHeight,但这只是在tableView函数中,所以我不知道如何调用它。

我不确定如何继续。 我并不是在寻找与.beginUpdates和.endUpdates有关的任何东西,因为我希望细胞生长是渐进的,最好是动画的。

任何帮助将不胜感激,因为我一直在寻找这个特定问题的答案很长一段时间。

包含rowHeight声明的代码:

  override func viewDidLoad() { super.viewDidLoad() // let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: Selector("longPress:")) // longPressRecognizer.minimumPressDuration = 1.0 // 1 second press // longPressRecognizer.delegate = self // self.view.addGestureRecognizer(longPressRecognizer) tableView.delegate = self tableView.dataSource = self tableView.allowsSelection = false self.tableView.reorder.delegate = self view.backgroundColor = UIColor(red:0.64, green:0.93, blue:0.78, alpha:1.0) tableView.backgroundColor = UIColor.clear tableView.rowHeight = 84 tableView.rowHeight = UITableViewAutomaticDimension // Do any additional setup after loading the view. } func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { return 100 } 

我不喜欢用单词详细解释事情,所以我只想包含一个相对较短的代码(也可作为gist ),其中包含解释基本知识的注释。 我并没有真正关注架构和清洁代码,我只专注于完成任务。 以此为代码 – 尝试在代码库中做得更好。

无论如何,代码应该是非常清楚和不言自明的,但我想在你深入研究之前为你画一幅大图。 在解决方案中,我将高度保持在CGFloat (可变cellHeights )数组中,并通过更改数组中的相应高度来修改给定行的高度。 该数组作为heightForRowAt实现的基础。

当长按开始时,我启动一个计时器,每隔0.1秒通过修改cellHeights数组中的高度并告诉tableView重绘自身来更新所选行的高度。 这种情况会发生,直到达到该给定行的限制,然后我只是取消(无效)计时器。

如果长按在达到极限高度之前结束,我只是明确取消定时器,以便在用户松开印刷机时单元停止放大。

就是这样。 我建议你使用EnlargingCellsOnLongPressController gist (或下面的代码,它是相同的代码),在你自己的设备上试试,阅读代码和评论,我相信你应该能够在你自己的情况下实现它。

 import UIKit class EnlargingCellsOnLongPressController: UITableViewController { // this will hold the indexPath of the cell we are currently enlarging var enlargingIndexPath: IndexPath? // dummy data model var modelItems: [String] = [] // we will need to keep the heights for each particular cell (since any can be resized) var cellHeights: [CGFloat] = [] // some height limit, I will set it for myself to 200 let limitHeight = CGFloat(200) // the enlarging itself will be done by a timer weak var timer: Timer? override func viewDidLoad() { super.viewDidLoad() // nothing special here tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell") tableView.estimatedRowHeight = 100 tableView.allowsSelection = false // creating some dummy data, 30 items, and for each a cell height that will start at 100 for index in 0..<30 { modelItems.append("Item \(index)") // by default we will start with 100 cellHeights.append(CGFloat(100)) } // please, use swift 4 and the new #selector syntax let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(longPress(longPressGestureRecognizer:))) longPressRecognizer.minimumPressDuration = 1 self.view.addGestureRecognizer(longPressRecognizer) } // following three methods should be clear override func numberOfSections(in tableView: UITableView) -> Int { return 1 } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return modelItems.count } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) cell.textLabel?.text = modelItems[indexPath.row] return cell } // for height for row we will return a specific height from cellHeights array override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { return cellHeights[indexPath.row] } @objc func longPress(longPressGestureRecognizer: UILongPressGestureRecognizer) { if longPressGestureRecognizer.state == UIGestureRecognizerState.began { let touchPoint = longPressGestureRecognizer.location(in: self.tableView) if let indexPath = tableView.indexPathForRow(at: touchPoint) { //when the press starts on a cell, we will keep the indexPath for the cell self.enlargingIndexPath = indexPath // and turn on enlarging self.startEnlarging() } } else if longPressGestureRecognizer.state == .ended { // when the press is ended, we can stop enlarging stopEnlarging() } } func startEnlarging() { // interval 0.1 second seems smooth enough (redraw seems to be animated anyway) timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true, block: { [weak self] (timer) in guard let strongSelf = self, let enlargingIndexPath = self?.enlargingIndexPath else { return } let oldHeight = strongSelf.cellHeights[enlargingIndexPath.row] // since the timer repeats every 0.1 second, this will enlarge the cell 20 points per second till limit // in one cycle I will enlarge the cell by two points let newHeight = oldHeight + 2 if newHeight < strongSelf.limitHeight { // if the newHeight did not reach limit, // update height and redraw tableView strongSelf.cellHeights[enlargingIndexPath.row] = newHeight strongSelf.tableView.beginUpdates() strongSelf.tableView.setNeedsLayout() strongSelf.tableView.endUpdates() } else { // reached maximum size, just cancel the timer strongSelf.stopEnlarging() } }) } func stopEnlarging() { // this just cancels the timer timer?.invalidate() } } 

UPDATE

为了完整起见,我使用autolayout和UITableViewAutomaticDimension创建了一个要点 ,如果您决定使用它而不是heightForRowAt 。 但原则是一样的。

 Declare property for height of the cell and return this property in the tableviews's delegate method heightForRowAtIndexPath method var heightForCell = 100 func longPress(longPressGestureRecognizer: UILongPressGestureRecognizer) { if longPressGestureRecognizer.state == UIGestureRecognizerState.began { let touchPoint = longPressGestureRecognizer.location(in: self.tableView) if let indexPath = tableView.indexPathForRow(at: touchPoint) { self. heightForCell = // height you want to set // now reload cell again } } }