Scroll custom UITableViewCell to right above keyboard? - ios

Currently I have a UITableView with custom cells and in each cell there is a UITextField, the problem is that sometimes the UITextField is covered by the UIKeyboard.
So right now I have the Y coordinate for the UIKeyboard and my UITableView is functioning properly with the cells.
So pretty much how can I use that Y coordinate (float), in order to scroll my UITableView to that Y coordinate plus the height of the cell in order to get it right above my UIKeyboard?
Also when I the keyboard hides, how would I reset the UITableView to its normal position that it was in?
Any advice would be appreciated!
Thanks!
CustomCell *cell = (CustomCell*)[[thetextField superview] superview];
CGRect cellRect = [cell convertRect:cell.frame toView:self.view];
float bottomCell = cellRect.origin.y - cellRect.size.height;
if (bottomCell >= keyboardY) {
NSIndexPath *indexPath = [thetableView indexPathForCell:cell];
[thetableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
}

One or the other of UITableView's
- (void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated;
- (void)scrollToNearestSelectedRowAtScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated;
I'm guessing that control isn't getting into the if statement. Consider skipping the y-coordinate check in favor of just scrolling the table view regardless of where it is.
CustomCell *cell = (CustomCell *)[[theTextField superview] superview];
NSIndexPath *indexPath = [theTableView indexPathForCell:cell];
[theTableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
OK, if you're sure it's getting called, then make sure your indexPath isn't nil, which may happen if cell isn't in the tableView or if it's not a cell.

UITableView adjust itself whenever the keyboard is displayed.
However, it won't do it if you didn't set the UITableViewCellSelectionStyle of your custom cell to UITableViewCellSelectionStyleNone.
i solved by using the below code.
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];

Related

IndexPath for next/previous UITextField within UITableView

I have searched stack overflow (Getting row of UITableView cell on button press) and have found many solutions that people claim to work but I have yet to find the perfect solution. I am trying to get the indexPath of the next/previous UITextField within my UITableView using a CGPoint so that I can scroll to it and make it first responder. Most of the time it is correct however if my text field is a previous field high up in the UITableView in another section I get the wrong result.
Here is the code (Note: nextTxtField is a UIView):
CGPoint point = [nextTxtField convertPoint:CGPointZero toView:tableView];
NSIndexPath *indexPath = [tableView indexPathForRowAtPoint:point];
[UIView animateWithDuration:0.03 delay:0.0 options:0 animations:^{
[tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:NO];
} completion:^(BOOL finished) {
dispatch_async(dispatch_get_main_queue(), ^(void){
[nextTxtField becomeFirstResponder];
});
}];
You may get the indexPath of by row/item of UITableView by calling :
[NSIndexPath indexPathForRow:row inSection:section];
[NSIndexPath indexPathWithIndex:index];
[NSIndexPath indexPathForItem:item inSection:section];
Once you get the indexPath, you may get the UITableViewCell by:
[_tableView cellForRowAtIndexPath:indexpath];
It returns a UITableViewCell. TypeCast it to your cell class (be sure about it).
Then you may grab hold of nextTxtField as:
[((YourCellClass *) cell).nextTxtField becomeFirstResponder]
after scrolling UITableView to that indexPath.

Keep expanded UITableViewCell fixed on top

I have implemented SKSTableView and I used this command:
[tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
when I press a cell that is expandable, and it goes on top. Now I'd like that when I scroll the expanded cell which went to top to stay fixed there until it's closed. Can I do that?
In UITableView you have the UIScrollView methods. So you can do something like this:
-(void)scrollViewDidScroll:(UIScrollView *)scrollView {
UITableViewCell *cell =[self.myTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
CGRect cellFrame = [cell convertRect:cell.frame toView:self.view];
if (self.isStickToTop) {
self.cell.frame = CGRectMake(0, 0, self.cellFrame.width, cellFrame.size.height);
}
else {
self.cell.frame = CGRectMake(0, scrollView.contentOffset.y, self.cellFrame.width, cellFrame.size.height);
}
}
The isStickToTop is your maintenance BOOLvariable that will indicate if the cell stick to top or not. Don't say u don't know ;)

Custom delete button for UITableViewCell without editing mode?

I made a UITableViewCell nib with a button on it. When the button is pressed, I want to delete the cell. The table view isn't in editing mode and I'm not using a standard UITableViewCell delete button.
I could store the row number in the button tag from cellForRowAtIndexPath, and use that to determine the row to delete, but when a cell is deleted, the button tags will be incorrect.
Any ideas how I can identify what button press relates to what row?
Like in this answer:
CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition];
If your button is a subview of cell's content view (as it should be). You can get the index path for the cell with button like this:
UIView *cellContentView = yourButton.superview;
UITableViewCell *cell = cellContentView.superview;
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
Then, just delete the cell:
[tableView beginUpdates];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView endUpdates];
if the method the button calls has a signature like:
-(void)action:(id)sender;
sender will be the UIButton that called the action so:
UIButton *button = (UIButton *)sender;
UITableViewCell *cell = [[button superview] superview];
should get you what you want.

Callback for cellForRowAtIndexPath?

My Project:
I have an UITableView in My project. Each and every UITableViewCell have one UITextView as a subview. When user tap on 'Add' button, I need to add one more UITableViewCell with UITextView to UITableView and I have to set focus into the added UITextView.
What I've Tried:
Once user tap on add button, I will update the numberOfRowsInSection of UITableView and subsequently I'll call [UITableView reloadData] to invoke [UITableView cellForRowAtIndexPath]. Here, I'll append the UITextView as subview of UITableViewCell.It Works fine until this point.
My problem:
I need to set focus into the UITextView Once after the [UITableView cellForRowAtIndexPath] get called. When I called the set focus method for UITextView after [UITableView reloadData], It is not working. I want to know, Is there any callback method for [UITableView cellForRowAtIndexPath]?
Thanks for your answers.
Try this,
In Add button action
//Assuming only 1 section, if you have more section find sections by `numberOfSections` method
NSInteger totalRows = [self.tableView numberOfRowsInSection:0];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:totalRows inSection:0];
[tableView beginUpdates];
[tableView insertRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationNone];
[tableView endUpdates];
//If you have custom cell
CustomCell *cell = (CustomCell *)[self.tableView cellForRowAtIndexPath:indexPath];
[cell.textView becomeFirstResponder];
//If you are not using custom cell, then set tag to textView and
//UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
//UITextView *textView = (UITextView *)[cell viewWithTag:kTextViewTag];
//[textView becomeFirstResponder];
after you have called your reloadData method you can do something like this:
To get a reference to the last row in the last section…
// First figure out how many sections there are
NSInteger lastSectionIndex = [self.myTableView numberOfSections] - 1;
// Then grab the number of rows in the last section
NSInteger lastRowIndex = [self.myTableView numberOfRowsInSection:lastSectionIndex] - 1;
// Now just construct the index path
NSIndexPath *pathToLastRow = [NSIndexPath indexPathForRow:lastRowIndex inSection:lastSectionIndex];
//Grab a reference of your cell from the last row
MyCustomCell *myCC = [self.myTableView cellForRowAtIndexPath:pathToLastRow];
//Use this cell reference to set focus to your UITextView
[myCC.myTextView setFirstResponder:YES];

Getting UITableViewCell from its superview iOS 7 issue

I have few UI objects in the cell that have got gesture recognizer instance. I need to get cell where pressing object is located. I have the method below for getting it, but it just work before iOS 7:
UITableViewCell *cell = (UITableViewCell *)[[[sender view] superview]superview];
for iOS 6 it return UITableViewCell
for iOS 7 it return UITableViewCellScrollView
I think the new cell has some additional views in iOS 7, that's why I grab UITableViewCellScrollView instead of UITableViewCell as before.
The best way to get a table view cell from it's subview is to convert the subview's location to a location in the table view, then ask the table view for the index path of the cell at that point:
CGPoint subviewPosition = [sender convertPoint:CGPointZero toView:self.tableView];
NSIndexPath* indexPath = [self.tableView indexPathForRowAtPoint:subviewPosition];
Then, you can get the cell for that index path:
UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:indexPath];
As you can see, relying on the view hierarchy is not a good approach - Apple can break it at any time.
You should use a delegate protocol to connect your cell to the controller.
CGPoint subviewPosition = [sender convertPoint:CGPointZero toView:self.tableView];
NSIndexPath* indexPath = [self.tableView indexPathForRowAtPoint:subviewPosition];
UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:indexPath];
NSIndexPath *path=[self.tableView indexPathForCell:cell];

Resources