Reputation: 28905
Given a UITableView
, how can I find the location of a specific UITableViewCell
? In other words, I want to get its frame relative to my iPhone screen, not relative to the UITableView
. So if my UITableView
is scrolled up, the location of each UITableViewCell
should be higher on the screen, etc.
Upvotes: 55
Views: 60037
Reputation: 16159
Swift 3
Relative to the tableView
:
let rect = self.tableView.rectForRow(at: indexPath)
Relative to the Screen
:
If you only know the cell
,
if let indexPath = tableView.indexPath(for: cell) {
let rect = self.tableView.rectForRow(at: indexPath)
let rectInScreen = self.tableView.convert(rect, to: tableView.superview)
}
If you know the indexPath
then don't need call the if
statement.
Upvotes: 17
Reputation: 6393
Swift-version of Tomasz and Jhaliya's answers in case anyone (else) struggles with this:
var cellRect = tableView.rectForRow(at: indexPath)
cellRect = cellRect.offsetBy(dx: -tableView.contentOffset.x, dy: -tableView.contentOffset.y)
Upvotes: 1
Reputation: 321
try it in
didSelectRowAtIndexPath
method
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
// get current location of selected cell
CGRect rectInTableView = [tableView rectForRowAtIndexPath:indexPath];
CGRect rectInSuperview = [tableView convertRect:rectInTableView toView:[tableView superview]];
NSLog(@"Cell Y Is %f",rectInSuperview.origin.y);
NSLog(@"Cell X Is %f",rectInSuperview.origin.x);
Upvotes: 9
Reputation: 5347
For future viewers, I was having trouble getting a reliable frame for cells in a UITableView
. I was trying to display a UIAlertController
in ActionSheet style on an iPad which needs a popover presentation. In the end this approach yielded the best results:
// 44 is the standard height for a cell in a UITableView
// path is the index path of the relevant row
// controller is the UIAlertController
CGRect frame = CGRectZero;
frame.origin.y = 44 * path.row;
frame.origin.x = table.frame.origin.x;
frame.size = CGSizeMake(table.frame.size.width, 44);
controller.popoverPresentationController.sourceRect = [tableView convertRect:frame toView:self.view];
controller.popoverPresentationController.sourceView = self.view;
Upvotes: 1
Reputation: 3466
Apart from rectForRowAtIndexPath you need to consider the scrolling.
Try this code:
// Get the cell rect and adjust it to consider scroll offset
CGRect cellRect = [tableView rectForRowAtIndexPath:indexPath];
cellRect = CGRectOffset(cellRect, -tableView.contentOffset.x, -tableView.contentOffset.y);
Upvotes: 64
Reputation: 559
Jhaliya's answer wasn't quite enough for me, I needed to do some more manipulations to get it working. My tableView was added to a viewController and its location on the right half way down the screen. So you need to take the tableView origin into account aswel as the scroll offset.
CGRect rowRect = [tableView rectForRowAtIndexPath:indexPath];
CGPoint offsetPoint = [self.infoTableView contentOffset];
// remove the offset from the rowRect
rowRect.origin.y -= offsetPoint.y;
// Move to the actual position of the tableView
rowRect.origin.x += self.infoTableView.frame.origin.x;
rowRect.origin.y += self.infoTableView.frame.origin.y;
Upvotes: 5
Reputation: 2737
If you really need to convert specifically to a point in the window, you could do this:
[yourAppDelegate.window convertPoint:[cell.contentView.center] fromView:[cell.contentView]];
I used the cells center coordinate, but you could use any point you want.
Vladimir is right, watch out for rows that are not visible (or that have been recycled).
-S
Upvotes: 0
Reputation: 31722
You could also use the rectForRowAtIndexPath
method to get the location of a UITableView
by sending the indexPath for that.
- (CGRect)rectForRowAtIndexPath:(NSIndexPath *)indexPath
So use as below:
CGRect myRect = [tableView rectForRowAtIndexPath:indexPath];
Upvotes: 101
Reputation: 170849
Try the following(sending nil as a toView parameter means you want to convert you rect to window coordinates):
CGRect r = [cell convertRect:cell.frame toView:nil];
And remember that if particular row is not currently visible then there may not be UITableViewCell for it - so before using that code you may need to check if cell is valid (not nil for example)
Upvotes: 23