i would like to get the indexPath of a cell which has a UITextField. Is it possible to get the indexPath of the current UITextField that we are using ?
If yes, it will be awesome to tell me, i'm getting crazy since 2 hours on it...
thanks a lot !
This should do the trick:
CGPoint location = [sender.superview convertPoint:sender.center toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:location];
another option would be to go up the view hierarchy. Adjust for your own view hierarchy:
UIView *contentView = [textField superview];
UITableViewCell *cell = [contentView superview];
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
Related
Say i’m loading UITableview with each UITextView inside each cell as subview.And i’ve assigned indexPath.row as tags for each textview.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"userDetails";
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
UITextView *textView=[[UITextView alloc]initWithFrame:CGRectMake(0, 0, self.frame.size.width, 60)];
NSString * myString = [contentArray1 objectAtIndex:indexPath.row];
textView.text= myString;
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc]
[tapRecognizer setNumberOfTouchesRequired:1];
[tapRecognizer setDelegate:self];
textView.userInteractionEnabled = YES;
textView.tag = indexPath.row;//assign tags to textview
[textView addGestureRecognizer:tapRecognizer];
[cell addSubview:textView];
return cell;
}
Below method gets called once the user taps on any textview.I’m seeing proper tag values printed when i tap on any textviews.
-(void) action:(id)sender
{
//NSLog(#"TESTING TAP");
UITapGestureRecognizer *tapRecognizer = (UITapGestureRecognizer *)sender;
NSLog (#"%d",[tapRecognizer.view tag]);
}
Now i would like to insert row in my tableview,say at index 3.
What i did is simple,
[contentArray1 insertObject:[NSString stringWithFormat:#"added cell”] atIndex:3];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:3 inSection:0];
[self.tableView insertRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
Now when i try to tap on any textviews after the inserted cell,i’m able to see the old tag values.Meaning,after row gets inserted to tableview at index=3,when i tap on textview i can see tag=2,then again when i tap on next cell’s textview i can see tag=2,it should be 3.
My question is,once we insert any row/cell in tableview,the tableview will not refresh other cell tags/index?….
I can fix it by calling reloadVisibleCells method.But i’m looking out for better solution.I don’t want to refresh whole screen just for inserting a row.Any solutions would be greatly appreciated.
Try to do it like this:
[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView endUpdates];
Your problem is that inserting/deleting rows doesn't cause reloading of other rows, and this is the expected and correct behavior. However, since -tableView:cellForRowAtIndexPath: is not called for those other rows, they are still configured with old (now obsolete) tags.
You can fix it in a number of ways (off the top of my head):
subclass UITableViewCell and store the represented object itself as its property (instead of the object's index)
associate the object with the UITableViewCell with objc_setAssociatedObject()
use -[UITableView indexPathForCell:] instead of tags to figure out a cell's real index path.
I try to program a tableview, where each cell contains its own textfield. When the user selects a textfield, the tableview should scroll, until the cell, which contains the selected textfield, is on the top of the visible part of the tableview. How can I do that?
In your cellForRowAtIndexPath, give tag to your every textfield like,
[[cell myTextField] setTag:[indexPath row]];
[[cell myTextField] setDelegate:self] ;
Implement UITextField Delegate method :
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:textField.tag inSection:0]
[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES]
}
I have created cell that can be expanded and collapsed, when the cell is expanded I add 2 subviews and remove those 2 subviews when cell is collapsed. Look at the code:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if(selectedIndex == indexPath.row){
selectedIndex = -1;
UITableViewCell *cell = [self.tblView cellForRowAtIndexPath:indexPath];
[[cell viewWithTag:TAG_KHMER] removeFromSuperview];
[[cell viewWithTag:TAG_KOREAN] removeFromSuperview];
//[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[self.tblView beginUpdates];
[self.tblView endUpdates];
return;
}
if(selectedIndex >= 0){
NSIndexPath *previousPath = [NSIndexPath indexPathForRow:selectedIndex inSection:0];
selectedIndex = indexPath.row;
UITableViewCell *cell = [self.tblView cellForRowAtIndexPath:previousPath];
[[cell viewWithTag:TAG_KHMER] removeFromSuperview];
[[cell viewWithTag:TAG_KOREAN] removeFromSuperview];
//[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
VocabularyController *vc = [self.vocabularyInfo objectAtIndex:indexPath.row];
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
UILabel *khmerLabel = [[UILabel alloc] init];
khmerLabel.text = vc.khmer;
khmerLabel.font = [UIFont fontWithName:#"Hanuman" size:17];
[khmerLabel setNumberOfLines:0];
khmerLabel.tag = TAG_KHMER;
khmerLabel.frame = CGRectMake(20, 45, 300, 300);
UILabel *koreanPro = [[UILabel alloc] init];
koreanPro.text = vc.korean;
[koreanPro setNumberOfLines: 0];
koreanPro.tag = TAG_KOREAN;
koreanPro.frame = CGRectMake(20, 315, 300, 300);
[cell addSubview:khmerLabel];
[cell addSubview:koreanPro];
selectedIndex = indexPath.row;
//[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[self.tblView beginUpdates];
[self.tblView endUpdates];
}
What happened is the cell seem not remove the previous one. it displays new text on the old text but when I click on the same cell twice again and then the cell can render the text good.
Can anyone help me how to display it properly.
After click twice times on the cell.
Don't try and add subviews like that - it's going to lead to confusion, because as you've found out UITableView recycles the cells.
Instead, create your own custom UITableViewCell subclass that can be switched between the various states you require, and has all the subviews already set up. You can do this in a number of ways - if you're using storyboards you can use prototype cells, or you can use a NIB, or you can create your custom subclass entirely in code (whichever you are most comfortable with).
Basically, don't add subviews to your cells in your table view delegate/datasource calls. Create a custom subclass, and you'll find everything much, much easier.
I have a table view in which each cell contains a button. I dont use the didSelectRowAtIndexPath delegate but my custom method for the button action. I want that on clicking the button inside each cell, that cell should be highlighted or change colour and return to its normal state(colour) when the button in some other cell is clicked(making this cell highlighted).My button action method is:
- (void)SelectButtonTapped:(UIButton *)button
{
self.tabBarController.tabBar.userInteractionEnabled = YES;
AppDelegate *proDel = [[UIApplication sharedApplication]delegate];
UITableViewCell *cell = (UITableViewCell *)button.superview.superview;
//MyCustomCell *cell = (MyCustomCell *)button.superview.superview;
NSIndexPath *indexPath = [homeTable indexPathForCell:cell];
//cell.backgroundColor = [UIColor lightGrayColor];
//[homeTable setNeedsDisplayInRect:[homeTable rectForRowAtIndexPath:indexPath]];
DetailViewController *objDetail=[[DetailViewController alloc] init];
Home *tempSearchObj=(Home *)[profileArray objectAtIndex:indexPath.row];
objDetail.firstName=tempSearchObj.userName;
objDetail.userImageUrl=tempSearchObj.imageUrl;
objDetail.passedProfileID = tempSearchObj.profileID;
plsSelectLabel.text = [NSString stringWithFormat:#"%#",objDetail.firstName];
proDel.globalName = plsSelectLabel.text;
proDel.globalProfileId = objDetail.passedProfileID;
}
But this doesn't seem to work. Any help would be appreciated!!
Set the cell selection style in cellForRowAtIndexPath as :
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
[cell setSelectionStyle:UITableViewCellSelectionStyleBlue];
}
And :
yourButton.tag = indexPath.row;
Add the following line in your method to highlight the cell :
UIButton *clickButton = (UIButton *)sender;
int addButtonIndex = clickButton.tag;
NSIndexPath *indexPathHighlight = [NSIndexPath indexPathForRow:addButtonIndex inSection:0];
UITableViewCell *newCell = [yourTable cellForRowAtIndexPath:indexPathHighlight];
[newCell setSelected:YES animated:YES];
Unselect previous cell :
NSIndexPath *previousIndexPathHighlighted = [NSIndexPath indexPathForRow:previousTag inSection:0];
UITableViewCell *previousCell = [yourTable cellForRowAtIndexPath:previousIndexPathHighlighted];
[previousCell setSelected:NO animated:YES];
previousTag = clickButton.tag;
The proper way to go about this is that on your cellForRowAtIndex: method you have a way of knowing if your cell needs to look highlighted or not. Then, after clicking on a button and configuring whatever you need to do, you should simply do
NSArray *indexes = [NSArray arrayWithObject:[NSIndexPath indexPathForRow:0 inSection:1]];
[self.tableView reloadRowsAtIndexPaths:indexes withRowAnimation:UITableViewRowAnimationNone];
The other way to go about this, is to access the cell and change it directly. But not with button.superview.superview, but rather
UITableViewCell *cell = [self.tableView cellForRowAtIndex:[NSIndexPath indexPathForRow:0 inSection:1]];
I think the best way to do it is to make a
NSInteger selectedCellIndex;
Set the tags of your buttons in the cellForRowAtIndex method
button.tag = indexPath.row
Set the selectedCellIndex when you click the button and reload the table
selectedCellIndex = button.tag;
[self.tableView reloadData];
Then in the cellForRowAtIndex method check if the index is the same as the selectedCellIndex and add a different color to the cell.
if( indexPath.row == selectedCellIndex ){
//set different colors
}
Remember to do this outside the if( cell == nil ) check, otherwise it wouldn't work.
This is the current working code.
But this should be simpler, I guess.
If I use the commented code I get a wrong height size.
Anyone some suggestions?
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
TableViewCell *cell = (TableViewCell *)[[self tableView]dequeueReusableCellWithIdentifier:CellClassName];
// TableViewCell *cell = [[[TableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellClassName] autorelease];
if (!cell)
{
NSArray *topLevelItems = [cellLoader instantiateWithOwner:self options:nil];
cell = [topLevelItems objectAtIndex:0];
// cell = [[[TableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellClassName] autorelease];
}
NSLog(#"cell height %f", cell.bounds.size.height);
[[self tableView] setRowHeight:cell.bounds.size.height] ;
}
Yes, you can definitely simplify it. Just call your own implementation of -tableView:cellForRowAtIndexPath: and use the cell that you get back from that, i.e.
UITableView *table = self.tableView;
NSIndexPath *index = [NSIndexPath indexPathForRow:0 inSection:0];
UITableViewCell *cell = [self tableView:table cellForRowAtIndexPath:index];
[table setRowHeight:cell.bounds.size.height]
Voilà: no more duplicated code.
On another note, you might want to do this in -viewDidLoad or -viewWillAppear: if your view controller is going to appear with animation. Doing it in -viewDidAppear: will cause the table’s row height to visibly jump when the view-presentation animation finishes.