Last active
February 16, 2018 15:28
-
-
Save MilanNosal/11eb84d3197dec6595dd5d04b0d98583 to your computer and use it in GitHub Desktop.
Example on how to implement enlarging a cell in UITableView during a long press on the cell
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// EnlargingCellsOnLongPressController.swift | |
// EnlargingCellsExample | |
// | |
// Created by Milan Nosáľ on 14/02/2018. | |
// Copyright © 2018 Milan Nosáľ. All rights reserved. | |
// | |
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() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment