swiftuitableviewanimationcgrectcgpoint

Current coordinates of a tableViewCell swift


fellows!

I'm trying to make an animation of an image in my tableViewCell. My intent is to get an imageView that is in a tableViewCell, add it to exactly the same place in a view, and then use scale animation. Currently, my code looks as below, however, I need to find a cell center point in every period of time (after scrolling too), that I can add image view exactly in the same place. The value of cellRect.origin.y constantly increases, whereas I need it to be exactly center.y point of my tableView cell. Could you please tell me where my mistake is?

Thank you in advanse!

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

    let cell = tableView.cellForRow(at: indexPath) as! TableViewCell

    cell.animateImageView = { [weak self]
        guard let self = self else { return }
        tableView.layoutSubviews()
        var cellRect = self.view.convert(tableView.rectForRow(at: indexPath), to: self.tableView)
        cellRect.origin.x = UIScreen.main.bounds.midX - (cell.photoImageView.frame.width / 2)
        cellRect.origin.y = cellRect.origin.y + (cell.photoImageView.frame.height / 2)
        UIView.animate(withDuration: 3) {
            
        } completion: { isFinished in
            
        }

    }

}

Solution

  • If I understand you correctly, this is your goal

    1. you tap on a UITableViewCell which has an imageView
    2. You want to create a new image view with the same image in the same position as the image in the cell you tapped
    3. Then from this position you will make this image full screen with animation
    4. You want to do something after the animation has completed

    If yes, there here are my thoughts

    I feel this line has the first issue:

    var cellRect 
       = self.view.convert(tableView.rectForRow(at: indexPath),
                           to: self.tableView)
    

    Let's take a look at the convert function in the docs

    Converts a rectangle from the receiver’s coordinate system to that of another view.

    Parameters

    rect

    A rectangle specified in the local coordinate system (bounds) of the receiver.

    view

    The view that is the target of the conversion operation. If view is nil, this method instead converts to window base coordinates. Otherwise, both view and the receiver must belong to the same UIWindow object.

    The receiver here is your cell's image view which you want to recreate so you should not call self.view.convert, it should be cell.photoImageView.convert

    The rect parameter is the bounds of your tapped cell's image view and the to parameter is self.view as you want to convert the image view's coordinates in the cell to the coordinates in the main view of the view controller.

    Beyond that I am not sure of the purpose of these as you will get the frame from the above function so I removed them but you can add it back if it makes sense to your application.

    cellRect.origin.x 
      = UIScreen.main.bounds.midX - (cell.photoImageView.frame.width / 2)
    
    cellRect.origin.y 
      = cellRect.origin.y + (cell.photoImageView.frame.height / 2)
    

    So this is how I changed the function:

    func tableView(_ tableView: UITableView,
                   didSelectRowAt indexPath: IndexPath)
    {
        // Retrieved the actual cell that was tapped
        // same as what you did
        let cell
            = tableView.cellForRow(at: indexPath) as! TableViewCell
        
        // Here I made a change based on my explanation above
        let cellRect =
            cell.photoImageView.convert(cell.photoImageView.bounds,
                                   to: view)
        
        // I created a blue view just for demo
        let aView = UIView(frame: cellRect)
        aView.backgroundColor = .blue
        view.addSubview(aView)
    }
    

    If you end it here, you will get this result

    Get coordinates of subview UIImageView imageview inside table view cell UITableViewCell UITableView

    The blue view added perfectly where we want it

    Now to complete the rest with animation is quite simple after we accomplished the tricky part and here is the full function

    func tableView(_ tableView: UITableView,
                   didSelectRowAt indexPath: IndexPath)
    {
        // Retrieved the actual cell that was tapped
        let cell
            = tableView.cellForRow(at: indexPath) as! TableViewCell
        
        // Here I made a change based on my explanation above
        let cellRect =
            cell.photoImageView.convert(cell.photoImageView.bounds,
                                   to: view)
        
        let animateImageView = UIImageView(frame: cellRect)
        animateImageView.image = cell.photoImageView.image
        animateImageView.clipsToBounds = true
        view.addSubview(animateImageView)
        
        UIView.animate(withDuration: 2.0)
        { [weak self] in
    
            if let strongSelf = self
            {
                animateImageView.frame = strongSelf.view.bounds
            }
    
        } completion: { (success) in
    
            if success
            {
                // animation completed, do what you want
                // like push your VC
            }
        }
    }
    

    The end result I believe is what you want

    Animate subview with coordinates of subview UIImageView from table view cell UITableViewCell UITableView

    I hope this helps you get you closer to your desired result