Reordering cell interactively with resized imageView - ios

I want to be able to reorder cells in my collectionview but have the cell that is moving's image be scaled down to a smaller size for the duration of the reorder. I am able to get the cell to resize while moving but there is an issue when the cell crosses over another cell and attempts to reorder. At the moment the cell reaches another cell, it temporarily resizes back to normal size, causing a flickering when moving it around.
I have followed this blog description for using Apple's methods to interactively reorder cells in a UICollectionView. The methods I am using are listed under the "Reordering Items Interactively" section of this page.
I have a UICollectionView subclass, a UICollectionViewCell subclass, and extensions for UICollectionViewDelegateFlowLayout, UICollectionViewDataSource, and UICollectionViewDelegate.
The way I am resizing the cell is by adding a boolean to my cell's subclass that is set to false by default but true when beginning and updating cell movement, and back to false when ending or canceling. In my sizeForItem method for the UICollectionViewDelegateFlowLayout extension, I am checking the boolean and returning a size accordingly.
It has been difficult to debug where the methods are getting the size to display when the cell's image returns to normal size for a split second, causing the flickering behavior, as each method is called many times to update the movement smoothly.
I am not married to resizing the cell in this way, if it is the cause of the issue, I'm just not sure how to resize it and prevent it from flickering when crossing over other cells in the collectionview.
Thank you in advance for any suggestions.
UPDATE
Some code samples.
I update the size of the bounds of imageView in beginInteractiveMovementForItem to shrink it initially. By the time the collectionview calls the update method, the size gets reset, but the cell gets its size from sizeForItem, below is my logic for that.
As a side note, I have also tried resizing the bounds of the cell itself in beginInteractiveMovement in addition to the imageView's bounds, but it had no effect so I removed that.
Here's how I'm handling resizing the imageView:
In the collection view's parent:
#objc func handleLongGesture(_ sender: UILongPressGestureRecognizer) {
switch(sender.state) {
case .began:
let location = sender.location(in: self.collectionView)
guard let selectedIndexPath = self.collectionView.indexPathForItem(at: location) else {
return
}
guard let dragCell = collectionView.cellForItem(at: selectedIndexPath) as? ActivityPhotoGalleryCell else { return }
UIView.animate(withDuration: 0.17, animations: {
dragCell.center = location
})
collectionView.beginInteractiveMovementForItem(at: selectedIndexPath)
case .changed:
collectionView.updateInteractiveMovementTargetPosition(sender.location(in: sender.view))
case .ended:
collectionView.endInteractiveMovement()
default:
collectionView.cancelInteractiveMovement()
}
}
In the collection view subclass:
override func beginInteractiveMovementForItem(at indexPath: IndexPath) -> Bool {
guard let dragCell = cellForItem(at: indexPath) as? CustomCellObject else { return false }
draggingCell = dragCell
dragCell.isDragging = true
return super.beginInteractiveMovementForItem(at: indexPath)
}
And here is my size for item logic:
var sizeForItem = CGSize(width: widthPerItem, height: widthPerItem)
let cell = collectionView.cellForItem(at: indexPath) as? CustomCellObject
if (cell?.isDragging ?? false) {
sizeForItem.height *= 0.7
sizeForItem.width *= 0.7
}
return sizeForItem

Related

Swift - Difficulty with different sized images in TableViewCell

I am loading a number of remote images with Kingfisher and having significant difficulty getting them to load correctly into a Tableview with cells of dynamic heights. My goal is to have the images always be the full width of the screen and of a dynamic height, how can this be achieved?
I asked a related question previously which led to understanding the basic layout using a stack view: SnapKit: How to set layout constraints for items in a TableViewCell programatically
So I've built something like the following:
With the following code (some parts removed for brevity):
// CREATE VIEWS
let containerStack = UIStackView()
let header = UIView()
let headerStack = UIStackView()
let title = UILabel()
let author = UILabel()
var previewImage = UIImageView()
...
// KINGFISHER
let url = URL(string: article.imageUrl)
previewImage.kf.indicatorType = .activity
previewImage.kf.setImage(
with: url,
options: [
.transition(.fade(0.2)),
.scaleFactor(UIScreen.main.scale),
.cacheOriginalImage
]) { result in
switch result {
case .success(_):
self.setNeedsLayout()
UIView.performWithoutAnimation {
self.tableView()?.beginUpdates()
self.tableView()?.endUpdates()
}
case .failure(let error):
print(error)
}
}
...
// LAYOUT
containerStack.axis = .vertical
headerStack.axis = .vertical
headerStack.spacing = 6
headerStack.addArrangedSubview(title)
headerStack.addArrangedSubview(author)
header.addSubview(headerStack)
containerStack.addArrangedSubview(header)
containerStack.addSubview(previewImage)
addSubview(containerStack)
headerStack.snp.makeConstraints { make in
make.edges.equalToSuperview().inset(20)
}
containerStack.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
Without a constraint for imageView, the image does not appear.
With the following constraint, the image does not appear either:
previewImage.snp.makeConstraints { make in
make.leading.trailing.bottom.equalToSuperview()
make.top.equalTo(headerView.snp.bottom).offset(20)
}
With other attempts, the image is completely skewed or overlaps the labels/other cells and images.
Finally, following this comment: With Auto Layout, how do I make a UIImageView's size dynamic depending on the image? and this gist: https://gist.github.com/marcc-orange/e309d86275e301466d1eecc8e400ad00 and with these constraints make.edges.equalToSuperview() I am able to get the images to display at their correct scales, but they completely cover the labels.
Ideally it would look something like this:
100 % working solution with Sample Code
I just managed to acheive the same layout with dynamic label contents and dynamic image dimensions. I did it through constraints and Autolayout. Take a look at the demo project at this GitHub Repository
As matt pointed out, we have to calculate the height of each cell after image is downloaded (when we know its width and height). Note that the height of each cell is calculated by tableView's delegate method heightForRowAt IndexPath
So after each image is downloaded, save the image in array at this indexPath and reload that indexPath so height is calculated again, based on image dimensions.
Some key points to note are as follows
Use 3 types of cells. One for label, one for subtitle and one for Image. Inside cellForRowAt initialize and return the appropriate
cell. Each cell has a unique cellIdentifier but class is same
number of sections in tableView == count of data source
number of rows in section == 3
First row corresponds to title, second row corresponds to subtitle and the 3rd corresponds to the image.
number of lines for labels should be 0 so that height should be calculated based on content
Inside cellForRowAt download the image asynchrounously, store it in array and reload that row.
By reloading the row, heightForRowAt gets called, calculates the required cell height based on image dimensions and returns the height.
So each cell's height is calculated dynamically based on image dimensions
Take a look at Some code
override func numberOfSections(in tableView: UITableView) -> Int {
return arrayListItems.count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
//Title, SubTitle, and Image
return 3
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch indexPath.row {
case 0:
//configure and return Title Cell. See code in Github Repo
case 1:
//configure and return SubTitle Cell. See code in Github Repo
case 2:
let cellImage = tableView.dequeueReusableCell(withIdentifier: cellIdentifierImage) as! TableViewCell
let item = arrayListItems[indexPath.section]
//if we already have the image, just show
if let image = arrayListItems[indexPath.section].image {
cellImage.imageViewPicture.image = image
}else {
if let url = URL.init(string: item.imageUrlStr) {
cellImage.imageViewPicture.kf.setImage(with: url) { [weak self] result in
guard let strongSelf = self else { return } //arc
switch result {
case .success(let value):
print("=====Image Size \(value.image.size)" )
//store image in array so that `heightForRowAt` can use image width and height to calculate cell height
strongSelf.arrayListItems[indexPath.section].image = value.image
DispatchQueue.main.async {
//reload this row so that `heightForRowAt` runs again and calculates height of cell based on image height
self?.tableView.reloadRows(at: [indexPath], with: .automatic)
}
case .failure(let error):
print(error) // The error happens
}
}
}
}
return cellImage
default:
print("this should not be called")
}
//this should not be executed
return .init()
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
//calculate the height of label cells automatically in each section
if indexPath.row == 0 || indexPath.row == 1 { return UITableView.automaticDimension }
// calculating the height of image for indexPath
else if indexPath.row == 2, let image = arrayListItems[indexPath.section].image {
print("heightForRowAt indexPath : \(indexPath)")
//image
let imageWidth = image.size.width
let imageHeight = image.size.height
guard imageWidth > 0 && imageHeight > 0 else { return UITableView.automaticDimension }
//images always be the full width of the screen
let requiredWidth = tableView.frame.width
let widthRatio = requiredWidth / imageWidth
let requiredHeight = imageHeight * widthRatio
print("returned height \(requiredHeight) at indexPath: \(indexPath)")
return requiredHeight
}
else { return UITableView.automaticDimension }
}
Related.
Another approach that we can follow is return the image dimensions from the API request. If that can be done, it will simplify things a lot. Take a look at this similar question (for collectionView).
Self sizing Collection view cells with async image downloading.
Placholder.com Used for fetching images asynchronously
Self Sizing Cells: (A Good read)
Sample
It’s relatively easy to do what you’re describing: your image view needs a width constraint that is equal to the width of the “screen” (as you put it) and a height constraint that is proportional to the width constraint (multiplier) based on the proportions of the downloaded image (aka “aspect ratio”). This value cannot be set in advance; you need to configure it once you have the downloaded image, as you do not know its proportions until then. So you need an outlet to the height constraint so that you can remove it and replace it with one that has the correct multiplier when you know it. If your other constraints are correct in relation to the top and bottom of the image view, everything else will follow as desired.
These screen shots show that this approach works:
(Scrolling further down the table view:)
It isn’t 100% identical to your desired interface, but the idea is the same. In each cell we have two labels and an image, and the images can have different aspect ratios but those aspect ratios are correctly displayed - and the cells themselves have different heights depending upon that.
This is the key code I used:
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! Cell
// in real life you’d set the labels here too
// in real life you’d be fetching the image from the network...
// ...and probably supplying it asynchronously later
let im = UIImage(named:self.pix[indexPath.row])!
cell.iv.image = im
let con = cell.heightConstraint!
con.isActive = false
let ratio = im.size.width/im.size.height
let newcon = NSLayoutConstraint(item: con.firstItem, attribute: con.firstAttribute, relatedBy: con.relation, toItem: con.secondItem, attribute: con.secondAttribute, multiplier: ratio, constant: 0)
newcon.isActive = true
cell.heightConstraint = newcon
return cell
There's a straight forward solution for your problem if you don't want to change your layout.
1- define your cell
2- put the UIImageView and other UI elements you like inside your cell and add these constraints for the image view:
-top,leading,trailing,bottom to superview
-height constraints and add outlet to your code (for example :heightConstraint)
3-Change the content fill to : aspect fit
4- Load your images via kingfisher or any other way you like, once you pass your image, check the size and calculate the ratio : imageAspectRatio = height/width
5-Set the heightConstraint.constant = screenWidth * imageAspectRatio
6-call layoutIfNeeded() for the cell and you should be ok!
*This solution works with any UI layout composition including stack views, the point is having a constraint on the images and letting the tableview figure it out how to calculate and draw constraints.
class CustomTableViewCell: UITableViewCell {
#IBOutlet weak var heightConstraint: NSLayoutConstraint!
#IBOutlet weak var sampleImageView: UIImageView!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
func configure(image:UIImage) {
let hRatio = image.size.height / image.size.width
let newImageHeight = hRatio * UIScreen.main.bounds.width
heightConstraint.constant = newImageHeight
sampleImageView.image = image
sampleImageView.layoutIfNeeded()
}
}
Result :

UI CollectionView in UICollectionView Cell Programmatically

Hi I am trying to make a home feed like facebook using UICollectionView But in each cell i want to put another collectionView that have 3 cells.
you can clone the project here
I have two bugs the first is when i scroll on the inner collection View the bounce do not bring back the cell to center. when i created the collection view i enabled the paging and set the minimumLineSpacing to 0
i could not understand why this is happening. when i tried to debug I noticed that this bug stops when i remove this line
layout.estimatedItemSize = CGSize(width: cv.frame.width, height: 1)
but removing that line brings me this error
The behavior of the UICollectionViewFlowLayout is not defined because: the item height must be less than the height of the UICollectionView minus the section insets top and bottom values, minus the content insets top and bottom values
because my cell have a dynamic Height
here is an example
my second problem is the text on each inner cell dosent display the good text i have to scroll until the last cell of the inner collection view to see the good text displayed here is an example
You first issue will be solved by setting the minimumInteritemSpacing for the innerCollectionView in the OuterCell. So the definition for innerCollectionView becomes this:
let innerCollectionView : UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
layout.minimumLineSpacing = 0
layout.minimumInteritemSpacing = 0
let cv = UICollectionView(frame :.zero , collectionViewLayout: layout)
cv.translatesAutoresizingMaskIntoConstraints = false
cv.backgroundColor = .orange
layout.estimatedItemSize = CGSize(width: cv.frame.width, height: 1)
cv.isPagingEnabled = true
cv.showsHorizontalScrollIndicator = false
return cv
}()
The second issue is solved by adding calls to reloadData and layoutIfNeeded in the didSet of the post property of OuterCell like this:
var post: Post? {
didSet {
if let numLikes = post?.numLikes {
likesLabel.text = "\(numLikes) Likes"
}
if let numComments = post?.numComments {
commentsLabel.text = "\(numComments) Comments"
}
innerCollectionView.reloadData()
self.layoutIfNeeded()
}
}
What you are seeing is related to cell reuse. You can see this in effect if you scroll to the yellow bordered text on the first item and then scroll down. You will see others are also on the yellow bordered text (although at least with the correct text now).
EDIT
As a bonus here is one method to remember the state of the cells.
First you need to track when the position changes so in OuterCell.swft add a new protocol like this:
protocol OuterCellProtocol: class {
func changed(toPosition position: Int, cell: OutterCell)
}
then add an instance variable for a delegate of that protocol to the OuterCell class like this:
public weak var delegate: OuterCellProtocol?
then finally you need to add the following method which is called when the scrolling finishes, calculates the new position and calls the delegate method to let it know. Like this:
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
if let index = self.innerCollectionView.indexPathForItem(at: CGPoint(x: self.innerCollectionView.contentOffset.x + 1, y: self.innerCollectionView.contentOffset.y + 1)) {
self.delegate?.changed(toPosition: index.row, cell: self)
}
}
So that's each cell detecting when the collection view cell changes and informing a delegate. Let's see how to use that information.
The OutterCellCollectionViewController is going to need to keep track the position for each cell in it's collection view and update them when they become visible.
So first make the OutterCellCollectionViewController conform to the OuterCellProtocol so it is informed when one of its
class OutterCellCollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout, OuterCellProtocol {
then add a class instance variable to record the cell positions to OuterCellCollectionViewController like this:
var positionForCell: [Int: Int] = [:]
then add the required OuterCellProtocol method to record the cell position changes like this:
func changed(toPosition position: Int, cell: OutterCell) {
if let index = self.collectionView?.indexPath(for: cell) {
self.positionForCell[index.row] = position
}
}
and finally update the cellForItemAt method to set the delegate for a cell and to use the new cell positions like this:
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "OutterCardCell", for: indexPath) as! OutterCell
cell.post = posts[indexPath.row]
cell.delegate = self
let cellPosition = self.positionForCell[indexPath.row] ?? 0
cell.innerCollectionView.scrollToItem(at: IndexPath(row: cellPosition, section: 0), at: .left, animated: false)
print (cellPosition)
return cell
}
If you managed to get that all setup correctly it should track the positions when you scroll up and down the list.

Why aren't the cells in my UICollectionView updating their size when I update the flow layout?

I have a grid of cells in a UICollectionViewController:
Pretty standard 3 column grid (based on approximate cell size, wider layouts have more cells)
The overall idea of the app is that a user taps a cell which counts down the specified time, and once the timer is complete it will unlock the next time. The first time is always unlocked:
After the first 3 buttons are tapped and have counted down
Tapping the same cell twice in succession removes all cells except the first and the one which was tapped twice, to allow the user to loop around.
Doing this should also update the collectionViewLayout to be only 2 columns of equal width which fill the screen, but at the moment the first and second cells are not resizing:
[After a button is tapped twice in succession](http:// i.imgur.com/cLvaApG.png)
The layout is definitely updated / invalidated because rotating the device updates the cells as expected:
[Rotated to landscape mode](http:// i.imgur.com/rngwzre.png)
[And rotated back to portrait](http:// i.imgur.com/ajwPr1J.png)
I'm sizing the cells as follows:
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
if repeating {
let target = collectionView.frame.width
let targetFraction = target / 2
return CGSize(width: targetFraction, height: targetFraction)
}
let target = CGFloat(125)
let frameRef = collectionView.frame.width
let frameWidthRemainder = frameRef % target
let frameWidthRounded = frameRef - frameWidthRemainder
let columnCount = frameWidthRounded / target
let columnWidth = frameRef / columnCount
return CGSize(width: columnWidth, height: columnWidth)
}
Repeating is a bool which is set / reset by tapping on the cells as part of an action:
#IBAction func circleProgressButtonTapped(sender: CircleProgressButton) {
...
if previouslySelectedButton == sender && !repeating {
repeating = true
collectionViewLayout.invalidateLayout()
buttons = [buttons[0], buttons[row]]
collectionView?.reloadData()
for button in buttons {
button.circleProgressButton.setNeedsDisplay()
}
}
...
}
When the device rotates, I'm resetting the layout with:
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
for button in buttons {
button.circleProgressButton.setNeedsDisplay()
}
collectionViewLayout.invalidateLayout()
}
Buttons is an array of the cells, which is populated / reset with:
func refreshView() {
if let min = defaults.valueForKey(userDefaultsKeys.min.rawValue) as? Int {
self.min = min
}
if let max = defaults.valueForKey(userDefaultsKeys.max.rawValue) as? Int {
self.max = max
}
buttons = []
collectionView?.reloadData()
for i in 0..<buttonCount {
guard let collectionView = collectionView else { break }
let indexPath = NSIndexPath(forRow: i, inSection: 0)
let multiplier = i + 1
let time = min * multiplier
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! CircleProgressButtonCollectionViewCell
cell.circleProgressButton.delegate = self
cell.circleProgressButton.value = time
cell.circleProgressButton.resetText()
cell.circleProgressButton.indexPath = indexPath
cell.circleProgressButton.progress = 0
cell.circleProgressButton.activeProgressColour = theme
cell.circleProgressButton.tintColor = theme
cell.circleProgressButton.setNeedsDisplay()
if i > 0 {
cell.circleProgressButton.enabled = false
}
buttons.append(cell)
}
}
I know this is probably not the best way to be making the cells, but any other way caused problems with the cell re-use. I.e. the progress in a cell would also be re-used.
I'm not even sure if the issue is collectionViewLayout.invalidateLayout() is not invalidating properly or what. It could just be the collectionView needs to be updated in some other way. I don't even know if it's the collectionView or the cell I should be focusing on. It's just weird that the first two cells are the only ones not updating, especially as I'm not doing anything different to them.
I would list everything I've tried but I'd be here a while. Among other things, I've tried:
if previouslySelectedButton == sender && !repeating {
...
collectionViewLayout.prepareLayout()
if let collectionView = collectionView {
collectionView.setNeedsDisplay()
collectionView.setNeedsLayout()
}
if let collectionViewLayoutCollectionView = collectionViewLayout.collectionView {
collectionViewLayoutCollectionView.setNeedsDisplay()
collectionViewLayoutCollectionView.setNeedsLayout()
}
collectionView?.setNeedsDisplay()
collectionViewLayout.collectionView?.setNeedsDisplay()
collectionView?.setNeedsLayout()
collectionViewLayout.collectionView?.setNeedsLayout()
collectionView?.reloadData()
buttons = [buttons[0], buttons[row]]
for button in buttons {
button.setNeedsLayout()
button.setNeedsDisplay()
}
I've tried setting the buttons array to empty, reloading, then populating it (generating entirely new cells) and reloading it again but even that doesn't work.
If I have to radically alter my entire approach, so be it.

Place UITableViewCell beneath siblings

I'm trying to build a custom UITableView that acts in a similar way to the reminders app.
Instead of the top-most visible cell scrolling off the display, I want it to be covered by the next cell so the cells appear to stack on top of one another as you scroll.
Currently I am using:
override func scrollViewDidScroll(scrollView: UIScrollView) {
let topIndexPath: NSIndexPath = tableView.indexPathsForVisibleRows()?.first as! NSIndexPath
let topCell = tableView.cellForRowAtIndexPath(topIndexPath)
let frame = topCell!.frame
topCell!.frame = CGRectMake(frame.origin.x, scrollView.contentOffset.y, frame.size.width, frame.size.height)
}
But the top cell is always above the second cell - causing the second cell to scroll under it.
Also if I scroll quickly this seems to misplace all of my cells.
EDIT: Have fixed this. Answer posted below for future reference.
For anybody searching this in the future.
Simply loop through all the visible cells and set their z position to their row number (so each cell stacks above the previous one).
The if statement tells the top cell to remain at the contentOffset of the scrollview and for all other cells to assume their expected position. This stops the other cells being offset if you scroll too quickly.
override func scrollViewDidScroll(scrollView: UIScrollView) {
// Grab visible index paths
let indexPaths: Array = tableView.indexPathsForVisibleRows()!
var i = 0
for path in indexPaths {
let cell = tableView.cellForRowAtIndexPath(path as! NSIndexPath)
// set zPosition to row value (for stacking)
cell?.layer.zPosition = CGFloat(path.row)
// Check if top cell (first in indexPaths)
if (i == 0) {
let frame = cell!.frame
// keep top cell at the contentOffset of the scrollview (top of screen)
cell!.frame = CGRectMake(frame.origin.x,
scrollView.contentOffset.y,
frame.size.width,
frame.size.height)
} else {
// set cell's frame to expected value
cell!.frame = tableView.rectForRowAtIndexPath(path as! NSIndexPath)
}
i++
}
}

Custom UIViewController transition where UITableViewCell grows to full screen and back?

I haven't been able to find any examples of this online. How can I achieve the following effect? Instead of the standard slide-to-left effect when tapping a table row, I'd like the view controller transition animation to look like the following:
User taps a cell in the table
The cell starts growing to fill the screen, pushing other rows above and below it "offscreen".
As the cell grows, cells elements (text, images, etc.) cross-fade into the new view's contents until the new view completely fills the screen.
I'd like to also be able to interactively transition back into the table view by dragging up from the bottom edge, such that the reverse of the above is achieved. i.e. view starts shrinking back into a normal table view cell as the "offscreen" cells animate back into position.
I've thought about taking a snapshot of the table and splitting it up at the points above and below the cell, and animating these snapshots offscreen as part of a custom view controller transition. Is there a better way? Ideally I'd like to not take snapshots, as I may want to have animations, etc., still happening in the table view rows as they fade offscreen.
First thing first, i have seen your post today and his is written in swift programming language.
the follwing code is to expand the selected cell to the full screen, where the subviews will fade out and background image will expands.
First complete cellForRowAtIndexPath, then in didSelectRowAtIndexPath,
func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!) {
isSelected = true
selectedCellIndex = indexPath.row
tableView.beginUpdates()
var cellSelected: UITableViewCell = tableView.cellForRowAtIndexPath(indexPath)!
cellSelected.frame = tableCities.rectForRowAtIndexPath(indexPath)
println("cell frame: \(cellSelected) and center: \(cellSelected.center)")
let newCell = cellSelected.frame.origin.y - tableOffset
println("new cell origin: \(newCell)")
var tempFrame: CGRect = cellSelected.frame
variableHeight = cellSelected.frame.origin.y - tableOffset
tempFrame.size.height = self.view.frame.height
println("contentoffset: \(tableView.contentOffset)")
let offset = tableView.contentOffset.y
println("cell tag: \(cellSelected.contentView.tag)")
let viewCell: UIView? = cellSelected.contentView.viewWithTag(cellSelected.contentView.tag)
println("label: \(viewCell)")
viewCell!.alpha = 1
UIView.animateWithDuration(5.0, delay: 0.1, options: UIViewAnimationOptions.BeginFromCurrentState, animations: {
tableView.setContentOffset(CGPointMake(0, offset + self.variableHeight), animated: false)
tableView.contentInset = UIEdgeInsetsMake(0, 0, self.variableHeight, 0)
tableView.endUpdates()
cellSelected.frame = tempFrame
viewCell!.alpha = 0
println("contentoffset: \(tableView.contentOffset)")
}, completion: nil)
}
then update your heightForRowAtIndexPath, as
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if isSelected && (selectedCellIndex == indexPath.row) {
return self.view.frame.height
}else {
return 100
}
}
Ignore this if already solved. and this might be helpful to others.

Resources