Determine coordinates of a UITableViewCell while scrolling - iphone

My goal is to have the UITableViewCells fade in/out when they are approaching the bounds of the UITableView and about to be covered/revealed.
The approach I have been trying is to get the coordinates of the UITableViewCell during a scroll event. The problem is that every cell seems to be at 0,0. I have tried converting the coordinates to the parent table and view, but they still come out at 0,0.
So in general, if anyone knows a way to get the coordinates, or of a better way to go about fading UITableViewCells in and out based on their position, I would greatly appreciate any advice you may have.
Thanks for your time,
Joel

The first step is to use
CGRect rectInTableView = [tableView rectForRowAtIndexPath:indexPath];
which will report the CGRect of a cell within the tableView. However, this value does not change as the tableView scrolls. It is the position relative to the first row of the table (and not the first visible row). To get the position of the cell on the screen you have to convert it to the superviews coordinate system using
CGRect rect = [tableView convertRect:rectInTableView toView:[tableView superview]];
So the following line does it all
CGRect rect = [tableView convertRect:[tableView rectForRowAtIndexPath:indexPath] toView:[tableView superview]];
Swift 4
// Consider the indexPath at row 1, section 0.
let rectWithinTableView : CGRect = self.tableView.rectForRow(at: IndexPath(row: 1, section: 0))
let rectWithSuperViewCoordinates : CGRect = self.convert(rect: rectWithinTableView, to: self.tableView.superview)

Why not an overlay with a partially transparent gradient PNG in a UIImageView that's less translucent at the top and bottom?
Messing with cell drawing in table scrolling is going to take a big performance hit.

You can call
- (CGRect)rectForRowAtIndexPath:(NSIndexPath *)indexPath;
to get the rect of any given cell. This will contain it's coordinates in the origin struct within the rect.

I suspect the cells are held within 'cell sized' subViews of the UITableView so you are seeing a frame relative to that view.
I don't have an actual an answer for you but, I would suggest checking out UIScrollView's delegate class: UIScrollViewDelegate. It responds to – scrollViewDidScroll: and you can manually work out your offset from that. UIScrollView is a superclass of UITableView.
You can convert points (such as your origin) to another view's co-ordinates using UIView's - (CGPoint)convertPoint:(CGPoint)point toView:(UIView *)view method.

Related

How to get the position of tableviewcell after scrolling the tableview

I want to get the position of UITableVIewCell relative to the screen, not relative to tableview. So, if I scroll the tableview, the position is updated.
You should use two steps to achieve this:
Get the CGRect information for a selected cell/header or footer by using one of these methods of UITableView:
- (CGRect)rectForHeaderInSection:(NSInteger)section;
- (CGRect)rectForFooterInSection:(NSInteger)section;
- (CGRect)rectForRowAtIndexPath:(NSIndexPath *)indexPath;
2. Convert the CGRect to table's container view by using UITableView's convertRect method. Eg. to get the current pos of the first header you can use this code:
CGRect rect = [mytable convertRect:[mytable rectForHeaderInSection:0] toView:[mytable superview]];
If you want these above dinamically you might want to include this code in UITableView's delegate method:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView_ {.....
One example what I've done using similar techniques is at github - how to make table header row fixed:
https://github.com/codedad/SO_Fixed_TableHeader_iOS
Hope it helps you!
You need to get position from child to parent:
float x = cell.frame.origin.x;
float y = cell.frame.origin.y;
UIView* parent = cell.parent;
while(parent != nil)
{
x += parent.frame.origin.x;
y += parent.frame.origin.y;
parent = parent.parent;
}
Use the -[UITableView rectForRowAtIndexPath:] method. Keep in mind that if you attempt to get this when the cell is off screen you will get unexpected results. You can then convert it to your view controller's view (which i think is what you mean by screen) with the -[UIView convertRect:toView:] method.
Ref: https://developer.apple.com/library/ios/documentation/uikit/reference/UITableView_Class/Reference/Reference.html#jumpTo_49
https://developer.apple.com/library/ios/documentation/uikit/reference/uiview_class/UIView/UIView.html#jumpTo_65

Get the position of an element

I'm having trouble trying to scroll up a tableView when the user start editing a UITextField displayed in one of the cells.
My problem is that I can't find a way to know the position of the UITextField in the view. If I try to do activeTextField.frame.origin.y, I get the position of the TextField inside the cell, but not inside the tableView.
The way I build the view is the following :
I've got a TableViewController, which creates cells using a custom class that initializes the UITextField. Then my TableViewController set the UITextField delegate to itself, so I can trigger the textFieldDidBeginEditing event. But if I try to NSLog the y origin of the TextField, I always get the same value for each UITextField, which is its position in the cell.
Any idea on how I can solve this?
It's always confusing with these coordinate system changes ...
This should work to get you the point in the table view coordinate system:
CGPoint textFieldCenter = textField.center;
CGPoint pointInTableView = [tableView convertPoint:textFieldCenter fromView:textField.superview];
If you want to have it in a different view, you should replace tableView with the view you want to have the coordinate in.
And if you want to get the cell in the table the textField was in:
NSIndexPath* path = [tableView indexPathForRowAtPoint:pointInTableView];
UITableViewCell* cell = [tableView cellForRowAtIndexPath:path];
To get the position of your textfield should use the UIView method convertRect:toView:
convertRect:toView: Converts a rectangle from the receiver’s
coordinate system to that of another view.
(CGRect)convertRect:(CGRect)rect toView:(UIView *)view
example :
CGRect textFieldFrame = [self.tableview convertRect:yourTextField.frame toView:self.view];
this should help you out
This is simple and easy way of doing what you want
Yes, try using this method :
- (void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated
When you prompt the keyboard, scroll the tableView to the selected cell it should bring the cell to the top of the screen.
try this
CGPoint locationinView=[cellView convertPoint:location fromView:tableView];
here location is the point of textField in cellView.

Get width/frame of entire UITableViewCell

I have a method where I have a (rendered) UITableViewCell*. I would like to know the width/frame of the entire cell.
cell.frame doesn't seem to work - it gives me the frame of a random cell. The closest I got is cell.contentView.frame but it doesn't include the area covered by the accessoryView (see http://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/TableView_iPhone/TableViewCells/TableViewCells.html#//apple_ref/doc/uid/TP40007451-CH7). cell.contentView.superview.frame doesn't work either - it gives me a frame at some arbitrary location just like cell.frame does.
cell.contentView.width + cell.accessoryView.width works except in cases where the accessory view is UITableViewCellAccessoryNone
Any ideas how I can get the entire frame/width of the UITableViewCell in all cases?
Try this,
NSLog(#"Cell Width = %f",cell.frame.size.width);
NSLog(#"Cell Height = %f",cell.frame.size.height);
It will show the current cell Width and Height.
This code gives you the frame of the particular cell selected by indexPath:
// Get the cell rect and adjust it to consider scroll offset
CGRect cellRect = [tableView rectForRowAtIndexPath:indexPath];
cellRect = CGRectMake(cellRect.origin.x - tableView.contentOffset.x, cellRect.origin.y - tableView.contentOffset.y, cellRect.size.width, cellRect.size.height);
cell.frame will always give you the frame of the cell you're messaging.
And even if it did return a random cell, you should still be able to use the width of the frame, because all the cells have the same width.
I think by default, a cell will use 100% of the width of the UITableView so a UITableView's width is equivalent to a cell's width and because you would likely have set your table cell height using:
[UITableView setRowHeight:tableCellHeight];
Where tableCellHeight is a number of your choice and UITableView is the name of your UITableView not the UITableView class itself.
Then you would have both the width and height of a table cell, or did I misinterpret your question?

how to get the position of an object within a UIView, within a UIScrollView

so lets say I have a UIScrollView, within it are 3 UIViews, within those there is a UISlider in each one. they are positioned vertically in the UIScrollView.
I now have a 4th UIView also in the UIScrollView which I wish to move around depending on the position of the slider which has been used.
so within my sliderChanged method which i pass the sender, i get the position of the slider, and adjust the position of the 4th UIWindow to its y. This works great on the first UIView, but once on another UIView which has forced me to scroll down, using the slider moves the 4th UIView but stays at the beginning of the UIScrollView
I am using:
[4thView setCenter:CGPointMake([4thView center].x, [slider center].y+10)];
what I need is to get the position of the slider relative to the content of the scrollView and not relative to its UIView, so that I may set the 4th view again relative to the scrollView content.
You can convert the points by UIView's instance methods.
- (CGPoint)convertPoint:(CGPoint)point toView:(UIView *)view
- (CGPoint)convertPoint:(CGPoint)point fromView:(UIView *)view
For example, I want to convert a ponint on the viewA to the scrollViewB's coordinates.
CGPoint aPtInScrollView = [viewA convertPoint:aPoint toView:scrollViewB];
Or, I want to know the position of viewA in scrollViewB.
CGPoint aPosViewA = [scrollViewB convertPoint:CGPointZero fromView:viewA];
Using the previous answer I took it a bit further to solve the issue I was having.
If you have multiple UITextView's within multiple UIView's all inside a single UIScrollView: this will animate and scroll to them.
This could be also be applied to UITextField's as well.
-(void)textViewDidBeginEditing:(UITextView *)textView {
[self.theScrollView setContentOffset:[self.theScrollView convertPoint:CGPointMake(textView.frame.origin.x, textView.frame.origin.y) fromView:textView.superview] animated:YES];
}
If you have labels above your textviews, just offset the x or y by that amount.

Get a UITableView to scroll up from the bottom / snap to the bottom, not the top

I have a table view which is many cases will only have one or two cells that don't fill the screen. In this case, I would like the cells to sit at the bottom, rather than the top. In other words they should "snap" to the bottom of the tableview.
I can force the table view to scroll them to the bottom like this:
CGPoint bottomOffset = CGPointMake(0, [self.tableView contentSize].height - self.tableView.frame.size.height);
[self.tableView setContentOffset:bottomOffset animated:NO];
However, this is only partially successful. First, it doesn't work if I put it in viewDidLoad or viewWillAppear, only in viewDidAppear, which means that the user sees the tableview with the cells at the top first, then they move to the bottom. Second, if they scroll the table view, when they let go it automatically "snaps" back up to the top.
Does anyone know how to change this behaviour?
One option to consider is to resize the UITableView itself based on how many rows you will be displaying. Presuming that your UITableViewDelegate implements heightForRowAtIndexPath one can then set the height of the UITableView in a viewWillAppear method by multiplying the number of rows by the height of each row.
Something like this:
CGRect frame = [myTableView frame];
frame.size.height = [[myTableView dataSource] tableView: myTableView numberOfRowsInSection: 0] *
[[myTableView delegate] tableView: myTableView heightForRowAtIndexPath: [NSIndexPath indexPathForRow: 0 inSection: 0]];
[myTableView setFrame: frame];
This example assumes your table has one section and each row is the same height. Computing the size would have to get a little more complicated if multiple sections are involved or if different rows might be different heights.
Regardless of how the height is calculated the essence of the idea though is to just make the table itself shorter, no taller than the one or two rows that it is displaying, rather than trying to force it into behaving differently.